Logs: liberachat/#haskell
| 2026-04-09 19:17:50 | <tomsmeding> | so I'd say still call by value, just with some syntax for passing a non-null pointer |
| 2026-04-09 19:19:10 | → | mulk joins (~mulk@pd95147f8.dip0.t-ipconnect.de) |
| 2026-04-09 19:20:40 | → | jmcantrell_ joins (~weechat@user/jmcantrell) |
| 2026-04-09 19:20:46 | <EvanR> | call by name on the other hand seems to step outside the subject of evaluation |
| 2026-04-09 19:22:33 | → | uli-fem joins (~uli-fem@115.128.112.118) |
| 2026-04-09 19:22:39 | <EvanR> | going by this gem https://en.wikipedia.org/wiki/Jensen%27s_device |
| 2026-04-09 19:22:39 | × | haskellbridge quits (~hackager@96.28.224.214) (Read error: Connection reset by peer) |
| 2026-04-09 19:23:03 | <EvanR> | https://en.wikipedia.org/wiki/Jensen's_device |
| 2026-04-09 19:25:24 | <tomsmeding> | I think "call by name" means "lazy evaluation" |
| 2026-04-09 19:26:17 | <tomsmeding> | the typical operational presentation I've seen of "call by name" is "`(\x -> e1) e2` reduces to `e1[e2/x]`", i.e. function application is just inlining of the argument _term_ into the function body |
| 2026-04-09 19:26:30 | <tomsmeding> | which is incredibly pointless as an actual operational implementation |
| 2026-04-09 19:26:51 | × | uli-fem quits (~uli-fem@115.128.112.118) (Ping timeout: 255 seconds) |
| 2026-04-09 19:26:59 | <tomsmeding> | but "call by name" is intended to be the semantics encompassing all operational behaviours that are semantically equivalent to that one, including call-by-need as GHC does |
| 2026-04-09 19:27:31 | <EvanR> | sometimes I think that 3 different names might be 3 different things, especially since algol predates GHC by a minute |
| 2026-04-09 19:28:41 | <EvanR> | but yeah I could see how jensen's device exploits basically lazy evaluation with side effects? |
| 2026-04-09 19:29:13 | → | haskellbridge joins (~hackager@96.28.224.214) |
| 2026-04-09 19:29:13 | ChanServ | sets mode +v haskellbridge |
| 2026-04-09 19:30:16 | <monochrom> | lazy evaluation is call by need. call by name differs from that by cloning instead of reuse. call by need: (\x -> x + x) (2*2) --> let x=2*2 in x + x. call by name: (2*2) + (2*2) |
| 2026-04-09 19:31:20 | <tomsmeding> | yes and who on earth cares about call by name as an operational behaviour |
| 2026-04-09 19:31:31 | × | redshuffle quits (~quassel@45.43.70.75) (Remote host closed the connection) |
| 2026-04-09 19:31:38 | → | redshuffle joins (~quassel@45.43.70.75) |
| 2026-04-09 19:31:52 | <EvanR> | I figured this was all operational semantics |
| 2026-04-09 19:32:44 | <monochrom> | People who simulate (with infelicity, you'll see!) lazy evaluation in SML or Scheme by converting my example to (\f -> f () + f()) (\_ -> 2*2) |
| 2026-04-09 19:33:22 | <EvanR> | yep that's inefficient |
| 2026-04-09 19:33:48 | <monochrom> | For example Lawrence Paulson in "ML for the Working Programmer"! |
| 2026-04-09 19:34:54 | <monochrom> | Fortunately he added a sentence "this kind of thing is nicer in Haskell" :) |
| 2026-04-09 19:42:37 | <acarrico> | tomsmeding: Anyone who uses NixOS/Nixpkgs cares about call by name as an operational behavior, see Eelco Dolstra's paper "Maximal Laziness". |
| 2026-04-09 19:43:11 | <tomsmeding> | they want it to be impossible to share any work? |
| 2026-04-09 19:43:39 | <acarrico> | You do share work due to maixmal laziness. |
| 2026-04-09 19:43:49 | <tomsmeding> | call by name does not share work |
| 2026-04-09 19:43:52 | <acarrico> | Every thing is "interned" or "hash consed" |
| 2026-04-09 19:44:09 | <tomsmeding> | call by need is the thing that's lazy and computes stuff at most once |
| 2026-04-09 19:44:18 | <monochrom> | reuse-vs-cloning is the same debate as recompute-vs-caching i.e. waste time vs waste space :) |
| 2026-04-09 19:44:18 | <acarrico> | A call by name strategy with interning and a memoized evaluator. |
| 2026-04-09 19:44:28 | <tomsmeding> | call by name + memoisation is call by need |
| 2026-04-09 19:44:54 | <tomsmeding> | but, depending on how it's implemented, possibly slower than a direct, mutating call-by-need implementation |
| 2026-04-09 19:45:09 | <acarrico> | tomsmeding: I would tend to call by need the "thunk" strategy, which is a bit different. |
| 2026-04-09 19:45:09 | <tomsmeding> | call by need is obviously useful, haskell has it |
| 2026-04-09 19:45:27 | <tomsmeding> | it's the "duplicate all the work yolo" of plain call-by-name that I claim to be useless |
| 2026-04-09 19:45:41 | <acarrico> | tomsmeding: In some sense it is just a very easy implementation strategy that happens to work very well for that DSL. |
| 2026-04-09 19:45:47 | <tomsmeding> | right |
| 2026-04-09 19:46:09 | <acarrico> | Anyway, it is an interesting paper. |
| 2026-04-09 19:46:52 | <monochrom> | Oleg once complained about memoizing a really long list taking too much memory. I think he believed that the list can be easily recomputed, not worth memoizing. |
| 2026-04-09 19:47:46 | <tomsmeding> | right, selective recomputation is a thing that optimising compilers of functional languages have to deal with, and it's tricky to do properly (i.e. without accidentally pessimising) |
| 2026-04-09 19:48:10 | × | weary-traveler quits (~user@user/user363627) (Remote host closed the connection) |
| 2026-04-09 19:48:20 | <acarrico> | The strategy is very useful when you want to intern your values anyway for some reason, usually to support fast equality checking and sets and so forth. |
| 2026-04-09 19:49:28 | <acarrico> | Guh, that seems like too much magic. |
| 2026-04-09 19:50:17 | <tomsmeding> | this conversation exemplifies the original reason why this topic was brought up though: the terms "call by name" / "call by need" / "call by value" etc. mean multiple different things at different levels of abstraction, and different people use different ones |
| 2026-04-09 19:50:55 | <tomsmeding> | the way I was originally explained call by name is how I just explained it here, which only useful as a semantics, not as an implementation |
| 2026-04-09 19:51:14 | <tomsmeding> | but clearly you have a different meaning in mind, which is related but not quite the same :p |
| 2026-04-09 19:52:44 | <acarrico> | I entered the channel in the middle of the conversation. Just thought I'd point out Dolstra's paper since it seemed relevant. But its a great topic for people to think about, in part because it does open up those ideas. Ultimately you realize that you don't want a default strategy, but you kind of need one to avoid going insane with verbosity. |
| 2026-04-09 19:55:16 | → | Lord_of_Life_ joins (~Lord@user/lord-of-life/x-2819915) |
| 2026-04-09 19:55:27 | <acarrico> | tomsmending: yes, and I thought hey, actually I know of a system where the semantics is the implementation. The rewrite rule really does just take a closed term e2 and do (/x . e)[e2/x] which is just sounds insane as an implementation, but it works. |
| 2026-04-09 19:55:54 | → | merijn joins (~merijn@host-cl.cgnat-g.v4.dfn.nl) |
| 2026-04-09 19:56:07 | × | Lord_of_Life quits (~Lord@user/lord-of-life/x-2819915) (Ping timeout: 244 seconds) |
| 2026-04-09 19:56:11 | <tomsmeding> | because you do memoisation on top of that |
| 2026-04-09 19:56:15 | <tomsmeding> | presumably :p |
| 2026-04-09 19:56:16 | <acarrico> | I've been toying with using it in a macro system the same way. |
| 2026-04-09 19:56:24 | <acarrico> | correct. |
| 2026-04-09 19:56:34 | <tomsmeding> | right, this is an approach I hadn't thought of yet |
| 2026-04-09 19:56:35 | <acarrico> | memoisation + interning |
| 2026-04-09 19:56:35 | Lord_of_Life_ | is now known as Lord_of_Life |
| 2026-04-09 19:56:37 | <tomsmeding> | it's cute |
| 2026-04-09 19:57:05 | <mauke> | hey, aren't make variables just call-by-name (without the 'call' part)? |
| 2026-04-09 19:57:41 | <tomsmeding> | if you call that call-by-name, then shell variables are too, as is string interpolation in any language |
| 2026-04-09 19:58:00 | → | pyook joins (~puke@user/puke) |
| 2026-04-09 19:58:00 | puke | is now known as Guest3956 |
| 2026-04-09 19:58:00 | pyook | is now known as puke |
| 2026-04-09 19:58:02 | <tomsmeding> | which is I guess technically true, but string concatenation is not really a programming language in my mind :p |
| 2026-04-09 19:58:03 | → | uli-fem joins (~uli-fem@115.128.112.118) |
| 2026-04-09 19:58:07 | <mauke> | no, shell variables are eager |
| 2026-04-09 19:58:10 | <acarrico> | yes because it is simple, but also it is super lazy, since thunks only replace values in certain known locations, but memozition replaces them everywhere, so (4 + 4) + (4 + 4) is more lazy than by need. |
| 2026-04-09 19:58:17 | <tomsmeding> | mauke: fair |
| 2026-04-09 19:59:07 | <acarrico> | mauke: In Makefiles maybe there are two ways to expand shell variables. |
| 2026-04-09 19:59:13 | <tomsmeding> | acarrico: as in, if you'd literally write `(4 + 4) + (4 + 4)`, only two additions would get executed? |
| 2026-04-09 19:59:28 | <acarrico> | Correct, think about it with interning and memoization! |
| 2026-04-09 19:59:32 | <tomsmeding> | fun |
| 2026-04-09 19:59:45 | <monochrom> | I think GNU Make has "v = ..." vs "v := ..." for by-name vs by-value, I forgot which is which. |
| 2026-04-09 20:00:04 | → | wootehfoot joins (~wootehfoo@user/wootehfoot) |
| 2026-04-09 20:00:11 | <tomsmeding> | oh right, Make has mutation in there too, I forgot |
| 2026-04-09 20:00:26 | <tomsmeding> | := is CBV, = is CBN I guess yes |
| 2026-04-09 20:00:36 | × | Guest3956 quits (~puke@user/puke) (Ping timeout: 250 seconds) |
| 2026-04-09 20:00:39 | <tomsmeding> | where N = name |
| 2026-04-09 20:00:46 | <monochrom> | Whereas POSIX Make, I know nothing. :) |
| 2026-04-09 20:00:57 | <mauke> | call me by your name |
| 2026-04-09 20:01:07 | <monochrom> | <--- spoiled by GNU Make |
| 2026-04-09 20:01:27 | <acarrico> | Nobody has been spoiled by make, only burned. |
| 2026-04-09 20:01:47 | <monochrom> | "call me by your name" should inspire a joke language for the next April 1. :) |
| 2026-04-09 20:01:59 | <EvanR> | make is life |
| 2026-04-09 20:02:37 | <monochrom> | The only burning from Make I have got so far is just that it doesn't do well with filenames that contain spaces. |
| 2026-04-09 20:02:58 | × | merijn quits (~merijn@host-cl.cgnat-g.v4.dfn.nl) (Ping timeout: 276 seconds) |
| 2026-04-09 20:03:44 | <monochrom> | Once upon a time when that Ant thing for Java just came out, I took a look with high hope. Nope, it's more redundant than makefiles. I went back to makefiles. |
| 2026-04-09 20:05:13 | <acarrico> | monochrom: make is the way to go, but you gotta keep it simple. Zig added a build system and then suddenly I couldn't program in Zig anymore. |
| 2026-04-09 20:05:23 | <monochrom> | Yeah I keep it simple. |
| 2026-04-09 20:05:25 | <acarrico> | I guess we are off topic. |
| 2026-04-09 20:06:27 | × | uli-fem quits (~uli-fem@115.128.112.118) (Ping timeout: 255 seconds) |
| 2026-04-09 20:11:10 | → | weary-traveler joins (~user@user/user363627) |
| 2026-04-09 20:13:56 | → | merijn joins (~merijn@host-cl.cgnat-g.v4.dfn.nl) |
| 2026-04-09 20:18:26 | × | merijn quits (~merijn@host-cl.cgnat-g.v4.dfn.nl) (Ping timeout: 244 seconds) |
| 2026-04-09 20:25:11 | × | comonad quits (~comonad@p200300d02717df00adc247ef70bd7367.dip0.t-ipconnect.de) (Ping timeout: 272 seconds) |
All times are in UTC.