OILS / doc / ysh-vs-python.md View on Github | oilshell.org

200 lines, 135 significant
1---
2---
3
4YSH Expressions vs. Python
5==========================
6
7The [YSH]($xref) expression language borrows heavily from Python. In fact, it
8literally started with Python's `Grammar/Grammar` file.
9
10This doc describes the differences, which may help Python users learn YSH.
11
12If you don't know Python, [A Tour of YSH](ysh-tour.html) explains the language
13from the clean-slate perspective.
14
15(TODO: A separate doc could compare commands/statements like `for` and `if`.)
16
17<div id="toc">
18</div>
19
20## Background
21
22YSH has dynamic types, much like Python. These are the main **data** types:
23
24 Null Bool Int Float List Dict
25
26Quick example:
27
28 var x = null
29 var y = f(true, 42, 3.14)
30 var z = [5, 6, {name: 'bob'}]
31
32## Literals
33
34Every data type can be written as a literal. Literals generally look like
35Python, so this section describes what's the same, and what's changed / added
36/ and removed.
37
38### Like Python: numbers and lists
39
40- Integers: `123`, `1_000_000`, `0b1100_0010`, `0o755`, `0xff`
41- Floats: `1.023e6`
42- Lists: `['pea', 'nut']`
43 - TODO: we want Python-like list comprehensions
44
45### Changed: booleans, strings, dicts
46
47- Atoms are `true`, `false`, and `null` (like JavaScript) rather than `True`,
48 `False`, and `None` (like Python).
49 - In YSH, we use capital letters for types like `Int`.
50
51- String literals are like **shell** string literals, not like Python.
52 - Double Quoted: `"hello $name"`
53 - Single quoted: `r'c:\Program Files\'`
54 - C-style: `$'line\n'` (TODO: change to J8 Notation)
55 - Unicode literals are `\u{3bc}` instead of `\u03bc` and `\U000003bc`
56
57- Dicts use **JavaScript** syntax, not Python syntax.
58 - Unquoted keys: `{age: 42}`
59 - Bracketed keys: `{[myvar + 1]: 'value'}`
60 - "Punning": `{age}`
61
62### Added
63
64- Shell-like list literals: `:| pea nut |` is equivalent to `['pea', 'nut']`
65
66- "Quotation" types for unevaluated code:
67 - Command / block `^(ls | wc -l)`
68 - Unevaluated expression `^[1 + a[i] + f(x)]`
69
70- Units on number constants like `100 MiB` (reserved, not implemented)
71
72<!--
73- Character literals are **integers**
74 - Unicode `\u{03bc}`
75 - Backslash: `\n` `\\` `\'`
76 - Pound `#'a'`
77- `:symbol` (could be used as interned strings)
78-->
79
80### Omitted
81
82- YSH has no tuples, only lists.
83- No lambdas (function literals returning an expression)
84- No closures, or scope declarations like `global` and `nonlocal`. (We would
85 prefer objects over closures.)
86- No iterators.
87 - Instead we have for loop that works on lists and dicts.
88 - It flexibly accepts up to 3 loop variables, taking the place of Python's
89 `enumerate()`, `keys()`, `values()`, and `items()`.
90
91## Operators
92
93Like literals, YSH operators resemble Python operators. The expression `42 +
94a[i]` means the same thing in both languages.
95
96This section describes what's the same, and what's changed / added / removed.
97
98### Note: YSH Does Less Operator Overloading
99
100YSH doesn't overload operators as much because it often does automatic
101`Str` &harr; `Int` conversions (like Awk):
102
103- `a + b` is for addition, while `a ++ b` is for concatenation.
104
105- `a < b` does numeric comparison, not lexicographical comparison of strings.
106 - (We should add `strcmp()` for strings.)
107
108### Like Python
109
110- Arithmetic `+ - * /` and comparison `< > <= =>`. They also convert strings
111 to integers or floats. Examples:
112 - `'22' < '3'` is true because `22 < 3` is true.
113 - `'3.1' <= '3.14'` is true because `3.1 <= 3.14` is true.
114
115- Integer arithmetic: `//` integer division, `%` modulus, `**` exponentiation.
116 - They also convert strings to integers (but not floats).
117
118- Bitwise `& | ~ ^ << >>`
119
120- Logical `and or not`
121
122- Ternary `0 if cond else 1`
123
124- Slicing: `s[i:j]` evaluates to a string
125
126- Membership `in`, `not in`
127
128- Identity `is`, `is not`
129
130- Function Call: `f(x, y)`
131
132### Changed
133
134- Equality is `=== !==`, because we also have `~==`.
135- String Concatenation is `++`, not `+`. Again, `+` is always addition.
136- Splat operator is `...` not `*`: `f(...myargs)`.
137
138### Added
139
140- Eggex match `s ~ /d+/`
141- Glob match `s ~~ '*.py'`
142- Approximate Equality `42 ~== '42'`
143- YSH sigils: `$` and `@`
144- `mydict.key` as an alias for `mydict['key']`
145
146### Omitted
147
148- No string formatting with `%`. Use `${x %.3f}` instead. (unimplemented)
149- No `@` for matrix multiply.
150- I removed slice step syntax `1:5:2` because `0::2` could conflict with
151 `module::name` (could be restored).
152
153## Syntax Compared With JavaScript
154
155This section may be useful if yo know JavaScript.
156
157- YSH uses `===` and `~==` for exact and type-converting equality, while JS
158 uses `===` and `==`.
159
160- Expressions are more like Python:
161 - YSH expressions use `and or not` while JS uses `&& || !`. In shell, `&& ||
162 !` are already used in the command language (but they're somewhat less
163 important than in YSH).
164 - The YSH ternary operator is `0 if cond else 1`, while in JS it's `cond ? 0 :
165 1`.
166 - Operator precedence rules are slightly different, but still C-like. They
167 follow Python's grammar.
168
169- Same differences as above, versus Python:
170 - `s ++ t` for string concatenation rather than `s + t`
171 - Shell string literals rather than JS string literals
172
173## Semantics Compared
174
175The runtime behavior of YSH is also similar to Python and JavaScript.
176
177### Versus Python
178
179- `Bool` and `Int` are totally separate types. YSH is like JavaScript, where
180 they aren't equal: `true !== 1`. In Python, they are equal: `True == 1`.
181
182- Strings are bytes, which may UTF-8 encoded, like Go. (In Python 3, strings
183 are sequences of code points, which are roughly integers up to
184 2<sup>21</sup>.)
185
186- We avoid operators that cause "accidentally quadratic" behavior.
187 - No `in` on `List`, since that's a linear search. Only `in` on `Dict`.
188 - The're not `++=` operator on strings.
189
190<!-- TODO: "N ways to concat strings " -->
191
192### Versus JavaScript
193
194- Strings are bytes, which may UTF-8 encoded, like Go. (In
195 JavaScript are sequences of UTF-16 code units, which are roughly integers up
196 to 2<sup>16</sup>.)
197- Undefined variables result in a fatal error like Python, not a silently
198 propagating `undefined` like JavaScript.
199
200