x = 2
x = "foo"
[y] = [3]
[y] = ["bar"]
Sorry, I didn't re-read the code before translating.807 karma · joined October 19, 2016
x = 2
x = "foo"
[y] = [3]
[y] = ["bar"]
Sorry, I didn't re-read the code before translating. def main():
x = 2
[x] = ["foo"]
y = 3
[y] = ["bar"]
print(x + y)
Seems about the same level of comprehensibility to me. Is there anything in particular you find difficult to understand?The second example is expanded out and not how a person would normally write it, but if you're familiar with the basic concepts it's using, it shows why it works very clearly; think of it like assembler.
main = do
let x = 2
let x = "foo"
y <- pure 3
y <- pure "bar"
putStrLn $ x ++ y
which is really the same as main =
let x = 2
in let x = "foo"
in pure 3 >>= \y ->
pure "bar" >>= \y ->
putStrLn $ x ++ y
So it works pretty naturally where each assignment is kind of like a new scope. If the type system is good, I don't think it really causes issues.Once you have good function names, which you should generally be spending a lot more effort on than good local variable names, you won't find any value in adding variables like `var foo = get_foo()`.
irb(main):001:1/ puts(%r
irb(main):002:1* a+
irb(main):003:0> .match? %q aaa )
trueSo, it doesn't have them in the classic Lisp sense. Conses are just pairs. Using them as such isn't exotic. (cons 1 2) being an error in Clojure isn't a minor thing, it's very unique compared to other Lisps. It has a very different definition of cons.
def
foo(x)
bar(x)
end
as an example of Ruby syntax being overly homogeneous.For my eyes, [] aren't distinct enough from () to make the second style preferable. I'd rather have indentation to set it apart.
> [0] https://news.ycombinator.com/item?id=20896327
That example isn't tail recursive, though. The Python version is more difficult to read because you're using a manual stack instead of relying on the built-in one. An iterative algorithm, whether written using lexical recursion or a for loop, would entirely remove the use of a stack, not just hide the stack in your language implementation. Converting an iterative algorithm between the two forms is a simple syntax transformation, and doesn't introduce bookkeeping like that. Converting a body recursive function to iterate with an in-language stack introduces a lot of noise even if you use tail recursion to do the iteration.
The tail recursive Haskell version of your Python isn't much better:
sumTree :: BTree -> Int
sumTree t = sumTree' [t] 0
where sumTree' [] total =
total
sumTree' (Leaf v : rest) total =
sumTree' rest (v + total)
sumTree' (Branch v l r : rest) total =
sumTree' (l : r : rest) (v + total)You still need to have a grasp on the difference between reference equality and value equality without getting into anything anyone would call tricks or implementation details (eg, after `x = []; y = []; x.append(1)`, how many elements does y have?).
When you say the type cannot change, that's ambiguous: do you mean the type of the value a variable holds, or the type of the value itself? In C (a statically typed language), "int x" means that x will always hold an int, but you can still assign a pointer to it, it just turns into an int (weak typing). In Python (a dynamically typed language), the variable "x" wouldn't have a type (so it could hold an int at one point and a string later), but the value it holds does, and because it's strongly typed, it would throw a type error if you attempted to use it in a place where it wanted a different type (eg, `1 + "2"` does not turn 1 into a string or "2" into an int).
Strong typing means that types cannot be substituted for other types. In C, you can write `int x = "one"` and the char * (address of) "one" is automatically converted to an int, or in Javascript you can write 1 + "2" and a string "1" is automatically created; depending who you're talking to, either or both of these qualify as weak typing.
They're both spectrums, and commonly confused with each other.
const x = cond1 ? a
: cond2 ? b
: c
becomes in Rust let x = if cond1 { a }
else if cond2 { b }
else { c }