1 | ---
|
2 | ---
|
3 |
|
4 | YSH Expressions vs. Python
|
5 | ==========================
|
6 |
|
7 | The [YSH]($xref) expression language borrows heavily from Python. In fact, it
|
8 | literally started with Python's `Grammar/Grammar` file.
|
9 |
|
10 | This doc describes the differences, which may help Python users learn YSH.
|
11 |
|
12 | If you don't know Python, [A Tour of YSH](ysh-tour.html) explains the language
|
13 | from 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 |
|
22 | YSH has dynamic types, much like Python. These are the main **data** types:
|
23 |
|
24 | Null Bool Int Float List Dict
|
25 |
|
26 | Quick 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 |
|
34 | Every data type can be written as a literal. Literals generally look like
|
35 | Python, 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 |
|
93 | Like literals, YSH operators resemble Python operators. The expression `42 +
|
94 | a[i]` means the same thing in both languages.
|
95 |
|
96 | This section describes what's the same, and what's changed / added / removed.
|
97 |
|
98 | ### Note: YSH Does Less Operator Overloading
|
99 |
|
100 | YSH doesn't overload operators as much because it often does automatic
|
101 | `Str` ↔ `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 |
|
155 | This 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 |
|
175 | The 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 |
|