5 ms·
When you write too much Haskell, your Python code starts to look like this: print('\n'.join( 'FizzBuzz' if x%5==0 and x%3==0 else 'Fizz' if
by exDM69 13y ago
When you write too much Haskell, your Python code starts to look like this:
print('\n'.join(
'FizzBuzz' if x%5==0 and x%3==0
else 'Fizz' if x%3==0
else 'Buzz' if x%5==0
else str(x)
for x in range(1, 101)))
I would really like to have a "let" expression in Python to avoid having to write a new function with a def statement when you could get away with a simple lambda or generator expression.
- clickok 13y ago"let = lambda" would be the same thing, wouldn't it?
- exDM69 13y agoYes, but in an incredibly verbose way. And a simple let->lambda conversion can't express things that Scheme's let* or letrec expressions let you do (in Haskell, a "let" or "where" expression is a "letrec").
- aaren 13y ago>>> let = lambda File "<stdin>", line 1 let = lambda ^ SyntaxError: invalid syntax Am I misunderstanding you?
- farinasa 13y ago>>> let = lambda x: 2*x >>> print let(4) 8 Edit: Awesome, downvoted for helping.
- Ideka 13y agoThat's not what they mean. The usage they are discussing is more like this, I believe. In a functional context, instead of doing: print expensive_computation(), expensive_computation() You can do: (lambda x: print x, x)(expensive_computation()) Which would be equivalent to, with an imaginary let syntax: (let x be expensive_computation(): print x, x)
- eriktaubeneck 13y agoI like this one. I don't know enough Haskell to have come up with it on my own (but I should!)
- loqi 13y agoIn the generator case you can define a poor man's let like this: def let(x): yield x And use it by "iterating": ... for x in range(1, 101) for divisible_by_5 in let(x % 5 == 0) Still not as nice as having actual syntax for it.
- piinbinary 13y agoYou can also hack the with statement to get a let block: import contextlib @contextlib.contextmanager def let(*values): yield values with let(1, 2, 3) as (a, b, c): print(a, b, c)
- gbog 13y agoI also tend to wrap loops in expressions like that. Then, in almost every interesting loop, I suddenly want to log something or add intermediary computation, and have to refactor into the good old boring for loop.
- Too 13y agoPipeline your generator through a logging generator :)
- msravi 13y agoJulia: print([(x%3==0) && (x%5==0) ? "FizzBuzz" : (x%3==0) ? "Fizz" : (x%5==0) ? "Buzz" : x for x in 1:100])
- akbarnama 13y agoCool!
- acqq 13y agoAnd when you write C carefully, the C code looks like this (thanks seanjensengrey and rhth54656 for ideas): int i; static char* a[] = { "%d\n", "Fizz\n", "Buzz\n", "FizzBuzz\n" }; for ( i = 1; i < 101; i++ ) printf( a[ (i%5==0)*2 + (i%3==0) ], i ); The loosely similar Python: for i in range( 1, 101 ): print( [ i,'Fizz','Buzz','FizzBuzz' ][ (i%5==0)*2 + (i%3==0) ] )
- acqq 13y agoAnd my Visual C 6 compiles the above C to this x86 asm with a single conditional jump, just for the loop: mov edi, DWORD PTR __imp__printf mov esi, 1 L1: mov eax, esi cdq mov ecx, 5 idiv ecx mov eax, esi mov ebx, 3 push esi mov ecx, edx neg ecx sbb ecx, ecx cdq idiv ebx inc ecx neg edx sbb edx, edx inc edx lea edx, DWORD PTR [edx+ecx*2] mov eax, DWORD PTR arr[edx*4] push eax call edi add esp, 8 inc esi cmp esi, 101 jl SHORT L1 The magic is in the neg sbb combination: The neg changes reg to two's complement but also sets or clears the CF if the argument was != 0 then sbb reg,reg effectively moves CF to the reg avoiding conditional jump for != 0.
- yew 13y agoTaking that a little further, const char *fb[][2] = {{"%d\n", "Fizz\n"}, {"Buzz\n", "FizzBuzz\n"}}; int i; for (i = 1; i <= 100; ++i) printf(fb[i % 5 == 0][i % 3 == 0], i); (It's a pity we have to specify the second dimension manually . . .)