• 2 Posts
  • 583 Comments
Joined 2 years ago
cake
Cake day: June 15th, 2023

help-circle
  • Map (Int, Int) Int. Kind of a bad example because tuples have special-case infix syntax, the general case would be Map Int (Either Int Bool). Follows the same exact syntax as function application just that types (by enforced convention) start upper case. Modulo technical wibbles to ensure that type inference is possible you can consider type constructors to be functions from types to types.

    …function application syntax is a story in itself in Haskell because foo a b c gets desugared to (((foo a) b) c): There’s only one-argument functions. If you want to have more arguments, accept an argument and return a function that accepts yet another argument. Then hide all that under syntactic sugar so that it looks innocent. And, of course, optimise it away when compiling. Thus you can write stuff like map (+5) xs in Haskell while other languages need the equivalent of map (\x -> x + 5) xs (imagine the \ is a lambda symbol).


  • barsoap@lemm.eetoProgrammer Humor@programming.devWhy make it complicated?
    link
    fedilink
    arrow-up
    28
    arrow-down
    1
    ·
    edit-2
    23 days ago

    The actual reason why let … in syntax tends to not use C-style “type var” like syntax is because it’s derived from the syntax type theory uses, and type theorists know about parameterised types. Generics, in C++ parlance, excuse my Haskell:

    let foo :: Map Int String = mempty

    We have an empty map, and it maps integers to Strings. We call it foo. Compare:

    Map Int String foo = mempty

    If nothing else, that’s just awkward to read and while it may be grammatically unambiguous (a token is a name if it sits directly in front of =) parser error messages are going to suck. Map<Int,String> is also awkward but alas that’s what we’re stuck with in Rust because they reasoned that it would be cruel to put folks coming from C++ on angle bracket withdrawal. Also Rust has ML ancestry don’t get me started on their type syntax.






  • To a (modern) compatibilist, free will is the capacity to respond to the same stimulus with different reactions, i.e. it’s equivalent to the cybernetic concept of degrees of freedom. As such, answer:

    “You can poke a ball-point pen and it’s going to do the same thing, over and over again: Extend and retract the lead. It is predictable because its internal complexity is below the threshold of chaos.” Then proceed to repeatedly poke them in the arm to see how many different reactions they have to that. Mentally prepare for a tickle fight.



  • Your ld.so contains:

    Entry point address: 0x1d780

    EDIT: …with which I meant, modulo brainfart: My libc.so.6 contains a proper entry address, while other libraries are pointing at 0x0 and coredump when executed. libc.so is a linker script, presumably because GNU compulsively overcomplicates everything.

    …I guess that’s enough for the kernel. It might be a linux-only thing, maybe even unintended and well linux doesn’t break userspace.

    Speaking of, I was playing it a bit fast and loose: _start is merely the default symbol name for the entry label, I’m sure nasm and/or ld have ways to set it to something different.



  • How does executing a program actually work?

    Way too long an answer for a lemmy post

    It has an executable flag, but what actually happens in the OS when it encounters a file with an executable file?

    Depends on OS. Linux will look at the first bytes of the file, either see (ASCII) #! (called a shebang) or ELF magic, then call the appropriate interpreter with the executable as an argument. When executing e.g. python, it’s going to call /usr/bin/env with parameters python and the file name because the shebang was #!/usr/bin/env python.

    How does it know to execute “main”?

    Compiled C programs are ELF so it will go through the ELF header, figure out which ld.so to use, then start that so that it will find all the libraries, resolve all dynamic symbols, then do some bookkeeping, and jump to _start. That is, it doesn’t: main is a C thing.

    Is it possible to have a library that can be called and also executed like a program?

    Absolutely. ld.so is an example of that.. Actually, wait, I’m not so sure any more, I’m getting things mixed up with libdl.so. In any case ld.so is an executable with a file extension that makes it look like a library.

    EDIT: It does work. My (GNU) libc spits out version info when executed as an executable.

    If you want to start looking at the innards like that I would suggest starting here: Hello world in assembly. Note the absence of a main function, the symbol the kernel actually invokes is _start, the setup necessary to call a C main is done by libc.so. Don’t try to understand GNU’s libc it’s full of hystarical raisins I would suggest musl.









  • NixOS. Gentoo gets into trouble when you need multiple versions of the same library at the same time. Also while the infrastructure supports it it’s annoying that gentoo doesn’t provide pre-built binaries, like yes some people might want to have reason to build their own bash but I think I’ll be fine with a standard build. NixOS? If you install something usually it’s going to be pre-built. Change a couple of configuration flags? May or may not be pre-built. You want to apply a custom patch? It’s going to seamlessly build from source.