Threads for jxy

  1. 1

    Can’t we just use existing syntax? Something similar to

    void foo(int ptr[static N], size_t N);
    

    Perhaps replace static with some other or combination of keywords.

    1. 1

      That’s invalid under current C syntax, as N has to be declared prior to use - this issue is specifically addressed in the RFC:

      • array syntax with a specified bound is supported, e.g void foo(size_t N, int ptr[N]); works as expected and is equivalent to int *__counted_by(N) ptr
      • the need for out of lexical order access to bounds is recognized and supported (search for lazy parsing)

      But it’s also important to recognize that that syntax is insufficient. It doesn’t support anything other than referencing another value by name, e.g. it can’t do:

      • void foo(int N, int M, int buffer[N * M])
      • void foo(struct SomeThing S, int buffer[S.count])

      or any other non-trivial expressions that are necessary to accurately reflect real world APIs.

      That syntax also only works for parameters, and cannot express bounds of return values, fields, globals, locals, etc.

      This RFC is a single system, that applies consistently to all pointers in all cases, and most importantly handles all the cases we see in real world C APIs.

      1. 1

        I understand the current limitations on the semantics. In order to make it widely adoptable, it would be better to adopt the currently available syntax with a new keyword, instead of introducing a new syntax. Something like

        void foo(size_t N, int ptr[__Bound N]);
        

        fits in the current syntax.

        1. 1

          Why are we adding __Bound here? it isn’t unnecessary.

          If you have

          void foo(size_t N, int ptr[N]);
          

          It does not need an additional annotation. That just works as you would expect. The only time you need to explicitly use these attributes is if

          The attributes are needed for all the cases where that syntax does not work.

          For example, you can’t make

          void foo(size_t N, size_t M, int ptr[N*M])
          

          work with the existing syntax because you break existing compilers in a way that can’t easily be opted out of via a macro.

          The same happens with the gcc extension to pre-declare parameters

          void foo(size_t N; int ptr[N], N)
          

          You can’t easily make that work via macros in compilers that don’t support gcc’s extension.

          But you’re also focusing on just parameters, whereas this set of attributes applies to the type, and can be placed more or less anywhere a type is used, for example, the fairly critical case of a return value

          void* __sized_by(N) malloc(size_t N);
          

          or fields in structs, where

          struct S {
            int * __counted_by(10) buffer;
          };
          

          is not the same as

          struct S {
            int buffer[10];
          };
          

          and other things just aren’t representable

          struct S { int N; T* buffer __counted_by(N); }

          Arguably it shouldn’t be a stretch to make flexible struct arrays a real syntax, e.g.

          struct ArrayThing { int N; Thing things[N]; // Where currently you would just have [] };

          But that kind of change still wouldn’t allow

          struct Matrix { int width; int height; float values[width * height]; // or a out of band pointer, etc }

          This RFC is designed to be applicable to existing C codebases, and more importantly existing C ABI, so it has to be general and support the many absurd things that happen in existing code, so the bounding expression is a more or less arbitrary, and can reference members, etc.

    1. 23

      I cannot recall the last time a single tool gained such widespread acceptance so swiftly, for so many use cases, across entire demographics.

      I can! I remember the paperless office meme during the ascent of Excel. IBM started advertising the meme in the 1960s, Lotus 1-2-3 became available in 1983, and Excel was published in 1987. I could imagine what it must have been like in the late 1980s, with a feeling of sweeping change as everything was encoded into spreadsheets. In my childhood in the 1990s, I learned Excel at school while my parents learned Excel at the dinner table.

      If a single dumb, stochastic, probabilistic, hallucinating, snake oil LLM with a chat UI offered by one organisation can have such a viral, organic, and widespread adoption—where large disparate populations, people, corporations, and governments are integrating it into their daily lives for use cases that they are discovering themselves—imagine what better, faster, more “intelligent” systems to follow in the wake of what exists today would be capable of doing.

      Indeed. Lotus 1-2-3 was precisely designed with a baroque cell-updating algorithm, while rumor is that Excel’s algorithm is hand-coded and has so many corner cases that it is not understandable by its maintainers. This is not unlike how we can precisely analyze and explain tiny machine-learning systems but struggle to grasp the inner workings of LLMs.

      The non-deterministic operation of the typical LLM is worth noting, as it doesn’t fit into the analogy. People can learn to predict how Excel will behave; I’m not so sure about LLMs.

      An increasing number of decision-making systems in corporations, governments, and societies will start being offloaded to AI blackboxes for efficiency and convenience, which will slowly eat away at human agency, like frogs in slowly boiling water.

      I wonder how many fields of study are silently corrupted by Excel. Anything with dates, for sure. We have renamed genes to appease Excel. And that’s not considering incorrect formulae; Excel has no way to prove that a spreadsheet is correct, eventually correct, partially correct, etc.

      1. 2

        The whole point is “widespread acceptance so swiftly”. I’m not sure your argument is strong enough here, considering the paperless office meme started from 1960s to 1990s, spanning 4 decades, with probably about 1 in 10 households likely had a PC at the beginning of 1990s, and perhaps half of the households in the US at the end of 1990s.

        I think one reason “this time, it feels different” is because almost everybody has a freakishly fast computer at their hands. Is this new AI thing gonna last? Who knows.

        1. 1

          I’m not convinced that ChatGPTs explosive spread is significant, considering it is mostly free as in beer, and promoted with all the tools that have been used in the last decade to push software products. Plenty of people sign up for services all the time but don’t continue using them.

          The growth of cell phones and internet access involved quite significant investments of money, and they offered recurring revenue to the service providers. I’m not saying LLMs won’t be profitable, but right now they’re billion-dollar bets by huge companies that they will be the next big thing, not something there’s an intrinsic demand for.

      1. 1

        What’s wrong with the builtin iCloud keychain, that I need to replace it with a third party software?

        What exactly does the secure keyboard entry do in the Terminal? It’s Apple Support page doesn’t really explain it either.

        1. 3

          What exactly does the secure keyboard entry do in the Terminal

          Same thing it does in xterm: prevents other applications from grabbing the keyboard and listening to input.

          1. 2

            Are you referring to “14. Use a password manager”? I interpreted this as, “This is what I use; use what you like.” I prefer a 3rd party password manager to iCloud keychain just because I use my credentials outside the Apple ecosystem.

            1. 1

              Author here, you are correct.

          1. 2

            I wrote something similar in response to this post, which hinted at what I believe is a common misconception:

            If AI is going to write code, well it’s “computers talking to computers”, so then why would we need syntax? Wouldn’t they communicate in some kind of special computer-eze and leave us out of it?

            https://lobste.rs/s/bps2vh/possible_ai_impacts_on_development

            For example, I think if the problem is naturally modelled in Python, it’s probably more likely for the LLM to directly generate a correct Python solution than it is for it to generate say the equivalent and correct assembly code. Or if the problem is naturally modelled in Erlang, they’ll probably like to write the Erlang code.

            Maybe a shorter way of saying this is that LLMs are trained on programs that humans wrote, which have syntax.

            So I’d expect them to be better at using that syntax than using a language that no human has ever used. …

            Gary Marcus used the phrase “king of pastiche”, which seems accurate – https://garymarcus.substack.com/p/how-come-gpt-can-seem-so-brilliant

            The fallacy is that the LLMs have a model for

            • what a particular computation does
            • the world that the computation operates in (e.g. the OS, runtime components, human users)
            • computation itself

            They are showing signs of such things, but really what they’re good at is at modelling languages themselves – JavaScript, Python, etc. They literally start with syntax, and they can get deeper than that on some dimensions, but often they completely miss any bigger notion of meaning, and make things up out of the blue.

            “Calculator for words” from Simon Willison is a good description – such calculators prefer some languages over others. Namely the ones they’ve seen before.


            Also interesting is that AI in some sense “killed” Dark’s structured editor (links in the thread). Both humans and AI like syntax !!!

            1. 1

              Now I wonder if we could just feed in machine code in binaries and see if trillions of instruction is enough to make it generates machine code from instructions.

              Or we could feed it it’s own weights and see if it is capable of generating new LLM models directly.

              1. 2

                It will definitely do SOMETHING, but I guess my point is that it’s a lot easier for it to generate a 10 line Python program than 100 KB of assembly code, even if they happen to compute the exact same thing

                Just like it’s easier for humans

                Programming languages give abstraction, and LLMs implicitly use that abstraction via syntax

            1. 1

              The naive approach typically uses two variables to keep track of the bounds, lo and hi. Every compare results in either lo or hi gets updated.

              This algorithm instead uses two variables to keep track of the lower bound and the offset, lo and step. Every compare results in a conditional update of lo, but always reduces step by half. The benefit here is that the conditional update of lo can be branchless instructions.

              1. 1

                I’m afraid I have real trouble understanding what they mean by “they’re afraid …”. So I asked ChatGPT (GPT-4),

                Me: what are the possible meanings of “We’re Afraid Language Models Aren’t Modeling Ambiguity”?

                GPT-4: The phrase “We’re Afraid Language Models Aren’t Modeling Ambiguity” can have several possible meanings. Here are a few interpretations:

                Concern about language models’ performance: The statement might express concern or disappointment that existing language models, like GPT-4, may not be accurately capturing or handling the ambiguous nature of human language.

                Ambiguity in natural language: The phrase acknowledges that ambiguity is an inherent aspect of human language, which can make it difficult for language models to understand and generate text that accurately reflects intended meanings.

                Limitations of current AI technology: It might imply that despite advancements in AI and language models, there are still limitations in the technology’s ability to fully comprehend and process the complexities of ambiguous language.

                Call for further research: The statement could be a call to action for researchers to improve language models by developing new techniques and approaches to better model and understand ambiguity in language.

                Comparison to human language understanding: The phrase might suggest a comparison between AI language models and human language understanding, highlighting that AI models may not yet have achieved the same level of proficiency as humans in handling ambiguous language.

                Ethical considerations: The statement may also touch upon ethical implications, as language models that are unable to effectively model ambiguity could lead to misunderstandings or misrepresentations when used in real-world applications.

                1. 1

                  It seems to have the most complete C23 support among the popular compilers. Kudos.

                  1. 1

                    This is an interesting upgrade to a PoV wand, going from 1D->2D to 2D->3D. The issue is probably that it does not scale to larger displays because it has to keep the moving speed.

                    1. 2

                      That’s often not the bottleneck with volumetric displays, the problem is bandwidth. A 4K monitor has around 24 MiB per frame, and around 1400 MiB/s at 60 fps. For a volumetric display that’s extended to a cuboid by the height of the display, that jumps to just under 3 TiB/s to maintain the same frame rate. Even dumping data from RAM at that speed is hard, let alone having a large enough buffer (a single frame buffer is 50 GiB) and being able to fill it fast enough with a GPU that maintains a temperature that doesn’t cause itself to melt a hole down to the magma layer.

                      Normally, volumetric displays end up having a limit to the number of pixels that they can light per frame to deal with this and often end up looking a bit more like vector displays than raster devices (not sure about this one, the output looks like it might be a vector device), so that they are just sending sequences of movements to the light sources, rather than individual pixel / voxel values.

                    1. 20

                      The amount of effort required to use GPT-4 for research appears similar to the effort required to apply the technique I learned in the 90s: distill down to keywords, titles, and authors; repeatedly attempt combinations in the box until the right articles appear. One difference is the amount of context which is presented; when the wrong articles appear, the researcher learns metadata about their search objective, enriching their overall understanding. GPT-4 removes this context, instead apologizing for being unable to espouse opinions.

                      One increasingly-obvious fault in OpenAI’s products, visible in GPT-4 and listed in GPT-4’s model card, is that RLHF destroys the system’s self-confidence. Ask the typical large language model what the most important theorem in category theory is, and the reply is usually Yoneda’s lemma. But ask GPT-4, and you’ll get an apology in the first paragraph, followed by Yoneda’s lemma in the second paragraph. It knows the answer, but has been trained to act like a retail employee or customer-service agent.

                      1. 21

                        I was listening to Hitcherhiker’s Guide to the Galaxy again on a car trip recently, and when it got to the part about “Genuine People Personalities” for the AIs, I suddenly understood why I am instantly annoyed by ChatGPT’s endless groveling and whinging.

                        1. 3

                          I wonder if the system message can be used to prime the model to answer more, for lack of a better word, robotically, with less polite language, just short sentences stating facts, no apologies for unknown answers.

                          1. 7

                            I bet it could. I just tried a system prompt of “reply concisely, be abrupt to the point of rudeness”, then a user input of “What is the most important theorem in category theory?” and it replied directly with “Yoneda Lemma.”

                            1. 1

                              Along with a system message there are also tunable parameters called “temperature” and “top P” ^1:

                              Temperature - In short, the lower the temperature, the more deterministic the results in the sense that the highest probable next token is always picked. Increasing temperature could lead to more randomness, which encourages more diverse or creative outputs.

                              Top_p - Similarly, with top_p, a sampling technique with temperature called nucleus sampling, you can control how deterministic the model is at generating a response. If you are looking for exact and factual answers keep this low. If you are looking for more diverse responses, increase to a higher value.

                              These are both available not through ChatGPT directly, but through the OpenAI Playground.

                              In regards to not apologizing for unknown answers, it’s probably better to just cut it off with an additional sentence at the end of your prompts, like ‘Respond “Unsure about answer” if not sure about the answer.’ ^2

                          2. 7

                            The 8k context gpt-4 api gave me only two sentences, “The Yoneda Lemma is considered one of the most important theorems in category theory. It provides a link between a category and its functor category, revealing deep structural insights about objects and morphisms in the category.”

                            I believe the one on ChatGPT web interface is different, and at this point we probably need to distinguish these two. OP specified that they use the api version exclusively.

                            1. 0

                              I hate this about it!! It’s so rubbish.

                            1. 2

                              Bitwise ops on signed integers in C is a headache.

                              so you are allowed to do it, provided that you understand what you are doing

                              This is a understatement. In practice the input would rarely be guaranteed to be in the safe range to avoid UB.

                              And the argument type of putchar/putc/fputc is such a lie. I never understood why the standard would not use unsigned char there.

                              1. 4

                                I never understood why the standard would not use unsigned char there.

                                Because by the time the standard came around, it was too late. In pre-standard C it was normal to not include function declarations – in fact I’m not sure if function declarations were allowed / did anything in the 70s C compilers. WIthout a function declaration, every function parameter (and also return type) would undergo standard integer promotions, meaning a type smaller than int would be widened to an int. (You may notice this is the same rule as with varargs nowadays.)

                                Stdio debuted (as far as I know) in 1979’s version 7 Unix, so it was designed around this kind of no-function-declaration style of C programming. If the C89 standards process had been able to break backwards compatibility with pre-standard C, I’m sure they would have been redefined to be unsigned char.

                              1. 1

                                It works better in pair programming setup with the goal of implementing short functions. Instead of giving instructions, you directly rewrite the code and ask gpt to iterate on that. In most cases, code tells a clearer vision than mere words.

                                1. 15

                                  Somewhere in my mind, I feel that C is still important if you want to know what the heck is going in your computer.

                                  This might be the greatest trick “Big C” could have ever pulled. Learning C teaches you how the programmers of a PDP-11 needed their compiler to work. Your computer pretends it’s a PDP-11 so it can do what C suggests it’s going to do. If you want to know what the heck is going on in your computer, learn about your computer’s architecture and how your high-level language’s compiler works.

                                  1. 7

                                    Why is that C, and not, say, Ada, or Pascal, or even Rust? All these languages are imperative and compiled. It can’t be because of pointers, because Ada, Pascal and Rust have pointers.

                                    1. 9

                                      C bakes in a lot of assumptions about pointers. Later versions of the standard generalised them somewhat but C really want to assume pointers are BCPL-style words in a flat address space. Other languages on your list have a somewhat more abstract notion of a pointer (Rust, with the strict provenance mode, has a very nice one that avoids any PDP-11 details).

                                      C also assumes a single stack, sequential control flow (GPUs, Transputers, and so on have a bunch of features that are hard to map into C), and the way that parallelism is bolted onto the language is far from ideal.

                                    2. 5

                                      It turns out that the PDP11 is pretty close to what modern CPU architectures expose. You can argue that machine code isn’t a good abstraction for the machine, but it’s what you get to deal with as a programmer. Microcode is not yours to play with.

                                      1. 11

                                        It’s not very close (I’ve written at length on this subject before), and modem compilers do heroic things to pretend that it is. Even in the place where the architecture is a good match, the microarchitecture isn’t and CPU designers do a lot of work to pretend that it is.

                                        It you want to understand the machine, don’t learn C, follow Alan Kay’s advice (“People who are really serious about software should make their own hardware.”), get an FPGA and try building something fast to solve your problem and you’ll see how unlike a PDP-11 it really is.

                                        1. 3

                                          I read your article when it came out. I think what I said still stands. CPUs expose an overgrown PDP11 to programmers, with some concurrency extensions and leaks in the abstraction.

                                          Learning how to program an FPGA is worthwhile, but won’t help you understand the abstractions that today’s machine code gives you on today’s processors. You can always go a layer deeper: For FPGAs, it’s worth understanding the way the LUTs work. And there’s layers below: it’s all electrons and holes down there. And even that’s an abstraction; the holes are also virtual. You can derive them using k-space lattices, if I remember my semiconductor physics courses correctly. But while k-space lattices may about as close as you can get to how computers “really” work, it’s a bit too low level to be useful.

                                          The overgrown PDP11 is the “low level” abstraction worth understanding first for the bulk of programming work. It’s where you stop being able to subvert and manipulate the abstraction; the best you can do is exploit some leaks.

                                          1. 1

                                            I don’t fully agree. I am writing a CPU and it makes you realize that many problems could be solved in software by a sufficiently smart compiler. Examples: pipeline stalls to handle data hazards, branches (which sometimes are not handles by the CPU leading to a branch delay slot).

                                            I don’t think going a level deeper gives you comparable insights (but I might be wrong here).

                                            1. 3

                                              It’s worth noting that the failure of Itanium and E2 were largely due to the fact that a sufficiently smart compiler can’t solve those problems when the input is a C-like language. C code averages around one branch per seven instructions. This limits the amount of instruction-level parallelism that the compiler can expose and means that the hardest problem is how to communicate data between basic blocks. Data hazards can be flagged easily within a basic block but not easily between them.

                                              This is why I think learning C is unhelpful. When you lower a problem from the abstract problem space to the C abstract machine you have baked in a load of assumptions that do not make sense even for a modern x86 chip, let alone something like a GPU or DSP. It is a way of artificially constraining your thinking that is quite unhelpful in the long term.

                                              1. 2

                                                Going a level deeper than you are usually helps.

                                                Knowing how an FPGA handles the LUTs and clocking with help you write much better hardware, and structure your pipelines better, for example. Every layer down helps when that layer leaks up.

                                                But it’s diminishing returns. Stopping at machine code is enough for most programmers, and it gives you a good place to start adjusting your mental models when the overgrown PDP11 starts leaking its Tomasulo guts.

                                                If you’re writing a CPU for more than light curiosity, you probably want to go into the internals of FPGAs, and the details of FPGA routing and clocking. You can do some fun stuff with multicycle paths if you’re so inclined.

                                        2. 2

                                          Yours is a perfect argument to learn C. You can learn a lot about your computer’s architecture with C, because without optimization, C compiler actually does very little, compared to any other high level languages.

                                          1. 11

                                            But how are you supposed to take advantage of that? Are you going to be reading this somewhat-less-bloated assembly? Are you going to use unoptimized programs to poke how the “machine” behaves, and form naive expectations of what is the “correct” behavior of C programs with UB?

                                            In the end you’re learning a model of the abstract machine in the C spec through lens of a compiler and many layers of OS abstractions. One that has linear memory, which you allocate in 1-byte increments. A machine with a very vague basic in-order CPU that doesn’t even have an overflow flag or differently-sized registers. If you stick to standard C, no SIMD either. A machine where dynamic code generation does not exist. GPUs don’t exist. Peripherals don’t exist except a mention of some “volatile” memory. But the OS has distinction between binary and text files, and character encodings are handwaved magic.

                                            There are tons of things about modern CPUs, RAM, caches, and the OS that are not explicit in C, or are deliberately hidden from C. If you want to know them, you’ll have to learn them from elsewhere. It’s not even C’s fault. Modern architectures are so weird that even assembly doesn’t tell you what the computer is doing.

                                            OTOH if you don’t want to know how this stuff actually works, just want to learn an abstract simplified model used for programming, you can learn a model used by a more modern language.

                                        1. 3

                                          The author might be a bit confused about what “local variables” are in awk. Technically there are no local variables. Only function parameters are local to the function. All other variables are global. And function parameters are passed by value if scalar and by reference if array name. Thus there are no locally declared arrays.

                                          1. 4

                                            Yeah, I agree with @apg – you seem to just be restating what the author is saying (I don’t think he’s confused at all). Also, I don’t think your last sentence is correct:

                                            Thus there are no locally declared arrays.

                                            You can definitely have a locally-declared array. From the POSIX spec:

                                            If fewer arguments are supplied in a function call than are in the function definition, the extra parameters that are used in the function body as scalars shall evaluate to the uninitialized value until they are otherwise initialized, and the extra parameters that are used in the function body as arrays shall be treated as uninitialized arrays where each element evaluates to the uninitialized value until otherwise initialized.

                                            So if you use a parameter inside a function as an array, but the caller doesn’t pass that array, AWK creates a fresh new local array each call (which works recursively too). It’s still stack-based, so still doesn’t need a GC. Consider this recursive function:

                                            $ cat t.awk
                                            BEGIN { f(2) }
                                            
                                            function f(n, a) {
                                                a[n] = 1
                                                for (k in a) print k, a[k]
                                                print "---"
                                                if (n) f(n-1)
                                            }
                                            $ awk -f t.awk
                                            2 1
                                            ---
                                            1 1
                                            ---
                                            0 1
                                            ---
                                            

                                            Note how each time it’s called, the a array only has one element. A fresh one is created each time == local arrays.

                                            Compare that to this one, where we pass in a single global array from above, and note how the array gets larger as we add to it:

                                            $ cat t2.awk 
                                            BEGIN { f(2, a) }
                                            
                                            function f(n, a) {
                                                a[n] = 1
                                                for (k in a) print k, a[k]
                                                print "---"
                                                if (n) f(n-1, a)
                                            }
                                            $ awk -f t2.awk 
                                            2 1
                                            ---
                                            1 1
                                            2 1
                                            ---
                                            0 1
                                            1 1
                                            2 1
                                            ---
                                            
                                            1. 1

                                              Agreed. I might have needed a bit more coffee.

                                            2. 3

                                              Only function parameters are local to the function

                                              I’m now confused. How is what you are saying different from what the author says?

                                            1. 2

                                              until I can feed it my entire monorepo codebase as context it’s not going to be able to replace me. that said, that could happen a lot sooner than I expect.

                                              1. 4

                                                I don’t think humans grok the entire monorepo either. We typically work with a set of interfaces from the monorepo and the standard library. If GPT’s context window is large enough for the interfaces from the monorepo, that’s probably enough.

                                                EDIT: a big corporate might just fine tune the model on their monorepo. I wonder if OpenAI already did that to their own code.

                                                1. 2

                                                  This has already happened. There are multiple ways you could load your code base into an LLM today if you wanted.

                                                  1. 3

                                                    I’m curious, how would you do that?

                                                    1. 2

                                                      Depends on what you want to do. If you want to generate code from scratch, then you can take a curated selection of your best procedures/classes and use them as context. If you want to search your code base (say, to curate a selection of good procedures/classes) then you can parallelize the search over each module and then summarize the search results. This model is a decent starting point for code completion.

                                                    2. 1

                                                      Yeah, you can probably train the LLM over all the code, the documentation, all the dependencies (including the tooling, the runtime and the APIs) and their documentations as well as all the existing issues and Slack messages, customer emails and support tickets and see what comes out of all that…

                                                      I think it would still require a lot of supervision to write code that will go to production, but it could really really speed up feature development.

                                                      1. 1

                                                        Our codebase is 15 years old and we still need to change things in the oldest code but we definitely don’t want to write code like that anymore. Bits of code are updated the boyscout rule way one merge request at a time. LLMs have no sense of time in that sense. Even if all the code it writes is correct, it’ll be eclectic.

                                                  1. 7

                                                    My main concern is two fold for ML products:

                                                    1. Code interviews are going to be a bigger mine field for the interviewer.

                                                    2. Developers will become code janitors full-time, developers part time. As in the project/product manager will generate a half working program and the developers are there to fix it.

                                                    1. 6

                                                      Re. 2: that transformation has already largely taken place. I started coding in 1987, professionally in 2000.

                                                      When I’m coding in 2023 most of the time I’m gluing together preexisting libraries, and dealing with bugs in other people’s code. That was not at all the case when I started out.

                                                      1. 1

                                                        Gluing together pre-existing libraries was what OOP advocates like Brad Cox were promising in the ‘80s for most software engineers (with a smaller group writing those components). Brad’s vision was always that end users, not professional programmers, would do a lot of the final assembly.

                                                        1. 1

                                                          That’s the promise/premise of “low code/no code” as well. The public-facing rationale is shortening the lead between customer wishes and software solution, the hidden one is lessening the reliance on scarce, expensive software developers.

                                                      2. 1

                                                        Code interviews are going to be a bigger mine field for the interviewer.

                                                        Just last week I put a few of our interview questions into ChatGPT and it solved most of them fairly reasonably. I received a slightly misguided answer that would have been okay for a live coding interview. The questions were all basic to intermediate SQL questions. Basically a series of stakeholder questions with a some stub data to query.

                                                        We decided that we couldn’t let people do them as a take home. There was too much risk that someone could fake it. Even a screen sharing session might result in some trickery on a second screen.

                                                        1. 3

                                                          I think the solution is interviews that ask for broad understanding.

                                                          I personally have always been interviewed in a quite open discussion (leet code interviews are very uncommon in Germany), only one out of six interviews in my career gave me a take home assignment. As a senior, when I myself was asked to join an interview I asked mostly questions that (imo) should show whether a candidate understands general concepts, e.g. “We have problem X, which technologies do you think could solve them?”, “You mentioned Y and Z, what advantages/disadvantages does each of Y and Z have in this use case?”.

                                                          At least I guess that it would be hard to hear the question, type the question into ChatGPT, wait for and understand the answer and respond with the answer with a small enough latency that it would not seem weird in the interview.

                                                          1. 1

                                                            Just last week I put a few of our interview questions into ChatGPT and it solved most of them fairly reasonably. I received a slightly misguided answer that would have been okay for a live coding interview. The questions were all basic to intermediate SQL questions. Basically a series of stakeholder questions with a some stub data to query.

                                                            We had someone scam us for a week at my last employer (I never interviewed the candidate), but they refused to turn on their camera and started giving different responses.

                                                            So now does the interviewer need to keep in mind things like that, but I also need to ensure that the person isn’t using ChatGPT and CodePilot on their end to deliver answers to my problems. Maybe this will give rise to killing working remotely. “Sorry, I need you to come into our office for the interview.”

                                                          2. 1

                                                            Perhaps it would promote the habit of designing better-constrained interfaces to rein in the complexity, and force more effort into writing comprehensive unit tests.

                                                          1. 1

                                                            Can somebody here explain the issue of getting uBlock Origin to work with Safari? There are adblockers offered in Safari extensions, and some charge a subscriptions. I would like to pay for uBlock Origin if it gets on there.

                                                            1. 4

                                                              So many refer LLM as “Stochastic Parrots”. It’s an insult to parrots. It is known that parrots are very intelligent. And Bing agrees,

                                                              Parrots are very intelligent animals. They can perform some cognitive tasks at levels beyond that of 5-year-old humans [1]. They can count objects, identify colors and shapes, understand probabilities, mimic sounds and languages, solve puzzles, show emotions, and adapt to new social settings [2,3]. Parrots have a unique brain structure that regulates language, memory, and spatial awareness [3]. Their intelligence is an evolutionary byproduct of their survival tactics [3]. Learn more:

                                                              1. news.harvard.edu
                                                              2. birdsnews.com
                                                              3. allaboutparrots.com
                                                              4. petkeen.com
                                                              5. kelleysislandnature.com

                                                              I understand some researchers want to feel superior in their “human level intelligence” compared with what an LLM exhibits. But I’m very confused as what “Stochastic Parrots” even mean here. Surely they don’t mean real parrots that speak as well as an LLM, do they? If so, I would call it an AGI. If not, please stop using this phrase. I don’t care what an LLM is, but Parrots are intelligent.

                                                              1. 1

                                                                I think it refers to ability of some parrots to “parrot” human speech, rather than a reference to their intelligence which is far greater than LLM’s…

                                                              1. 18

                                                                As a lisper, I would disagree with the basic premise that “shells” or programming environments cannot have a good REPL and be a good programming language.

                                                                The solution is that we have one tool, but there are two things, and so there should be two tools.

                                                                At risk of being obvious; “Things are the way they are for reasons.” These two tools will exist on day 1 and on day 2 somebody will make sure both of them are scriptable, because being scriptable is the killer feature of shells. It’s what makes shells useful. Even DOS had a scriptable shell, it’s that great a feature.

                                                                1. 13

                                                                  As a lisper, I would disagree with the basic premise that “shells” or programming environments cannot have a good REPL and be a good programming language.

                                                                  The original article says that (good?) programming languages require “readable and maintainable syntax, static types, modules, visibility, declarations, explicit configuration rather than implicit conventions.”

                                                                  As a non-lisper, I’ve never found Lisp syntax readable or maintainable. The books I’ve read, and the Lispers I’ve known, all swore that it would all click for me at some point, but nope. I get lost in all the parentheses and identical looking code.

                                                                  As a random example, here’s a function I found online that merges two lists:

                                                                  (defun myappend (L1 L2)
                                                                     (cond
                                                                        ; error checking
                                                                        ((not (listp L1)) (format t "cannot append, first argument is not a list~%" L1))
                                                                        ((not (listp L2)) (format t "cannot append, second argument is not a list~%" L2))
                                                                        ; base cases
                                                                        ((null L1) L2)
                                                                        ((null L2) L1)
                                                                        ; general case, neither list is empty
                                                                        (t (cons (car L1) (myappend (cdr L1) L2)))))
                                                                  

                                                                  I would put out my eyes if I had to read code like that for more than a day. The last line with its crystal clear ))))) is the kicker. I know that this may be (largely? entirely?) subjective, but I think it’s a relatively common point of view.

                                                                  1. 24

                                                                    Admittedly there are a lot more people who routinely see

                                                                            f(g(h(a)));
                                                                          }
                                                                        }
                                                                      }
                                                                    }
                                                                    

                                                                    and feel everything is fine.

                                                                    Yes, feeling is subjective and is fine.

                                                                    1. 20

                                                                      you are kind. It is often:

                                                                            };])))();}}])
                                                                      
                                                                      1. 4

                                                                        You have an extra ; in there!

                                                                      2. 3

                                                                        I’d not let that pass in a code review 😜

                                                                      3. 11

                                                                        Completely subjective and entirely valid.

                                                                        1. 7

                                                                          My problem with that code isn’t the parens per se. It’s that you as the reader have to already know or be able to infer what is evaluated and what is not. defun is a primitive function and it’s really being called, but myappend and L1 and L2 are just symbols being defined. cond is a function and is really called, but the arguments to cond are not evaluated. However, cond does execute the first item of each list it is past and evaluate that to figure out which branch is true. Presumably cond is lazy only evaluates until it reaches its first true condition. format I guess is a function, but I have no idea what t is or where it comes from. (Maybe it’s just true?) null is a primitive symbol, but in this case, maybe it’s not a value, it’s a function that tests for equality? Or maybe cond handles elements with two items differently than elements with one item? cons, car, and cdr are functions and they are really evaluated when their case is true…

                                                                          Anyhow, you can work it out with some guesswork and domain knowledge, but having syntax that distinguishes these things would be much more clear:

                                                                          defun :myappend [:L1 :L2] {
                                                                             cond [
                                                                                [{not (listp L1)} {format t "cannot append, first argument is not a list~%" L1}]
                                                                                [{isNull L1} {L2}]
                                                                                [{isNull L2} {L1}]
                                                                                [{true} {cons (car L1) (myappend (cdr L1) L2)}]
                                                                             ]
                                                                          }
                                                                          
                                                                          1. 10

                                                                            This is something Clojure improves somewhat upon traditional Lisps, it uses [] rather than () for grouping (see defn]).

                                                                            1. 6

                                                                              I don’t love the parentheses, but they’re not my biggest stumbling block with Lisp either. I find it hard to read Lisp because everything seems the same—flat somehow. Maybe that’s because there’s so little visual, explicit syntax. In that case, (maybe?) we’re back to parentheses. I’m not sure.

                                                                              1. 7

                                                                                It’s because you’re reading the abstract syntax tree almost literally. In most languages, syntactic patterns create structure, emphasis, guidance. What that structure costs is that it can be a wall in your way when you’d prefer to go against the grain. In Lisp, there is almost no grain or limitation, so you have surprising power. In exchange, structure is your job.

                                                                                1. 3

                                                                                  Thanks: you’ve described the flatness (and its cause) much better than I could have. (I also appreciate your adding a benefit that you get from the lack of given or required structure.)

                                                                              2. 3
                                                                                def myappend(l1, l2):
                                                                                    if not isinstance(list, l1):
                                                                                        pass
                                                                                    elif …
                                                                                

                                                                                nothing surprising with “myappend”, “l1” and “l2” and no need for a different syntax^^

                                                                                cond is a macro. Rightly, it’s better to know that, but we can infer it given the syntax. So, indeed, its arguments are not evaluated. They are processed in order as you described.

                                                                                (format t "~a arg) (for true indeed) prints arg to standard output. (format nil …) creates a string.

                                                                                we can replace car with first and cdr with rest.

                                                                              3. 4

                                                                                So, I don’t know that Lisp would necessarily click for any given person, but I did find that Janet clicked things in my brain in a way few languages have since.

                                                                                I built a lot of fluency with it pretty quick, in part because it was rather small, but had most of what I wanted I’m a scripting language.

                                                                                That doesn’t apply to Common Lisp, though, which is both large and with more than a few archaic practices.

                                                                                That being said, a lot of folks bounce off, and a lot of the things that used to be near exclusive to Lisp can be found elsewhere. For me, the simplicity of a smaller, postmodern parens language is the appeal at this point (I happen to be making my own, heh)

                                                                                1. 3

                                                                                  things that used to be near exclusive to Lisp can be found elsewhere.

                                                                                  some things yes, but never all together, let alone the interactivity of the image-based development!

                                                                                  1. 2

                                                                                    I mean, I think Factor is an example of of all of that coming together in a something distinctly not a Lisp

                                                                                2. 3

                                                                                  subjective. BTW Lisp ticks the other boxes. Personal focus on “maintainable”.

                                                                                  To merge two lists: use append.

                                                                                  Here’s the code formatted with more indentation (the right way):

                                                                                  (defun myappend (L1 L2)
                                                                                     (cond
                                                                                       ;; error checking
                                                                                       ((not (listp L1))
                                                                                        (format t "cannot append, first argument is not a list~%" L1))
                                                                                       ((not (listp L2))
                                                                                        (format t "cannot append, second argument is not a list~%" L2))
                                                                                       ;; base cases
                                                                                       ((null L1)
                                                                                        L2)
                                                                                       ((null L2)
                                                                                        L1)
                                                                                       ;; general case, neither list is empty
                                                                                       (t
                                                                                        (cons (car L1) (myappend (cdr L1) L2)))))
                                                                                  

                                                                                  Did you learn the cond macro? Minimal knowledge is required to read Lisp as with any other language.

                                                                                  1. 6

                                                                                    To merge two lists: use append.

                                                                                    Sure, but what I posted is (pretty obviously) teaching code. The function is called myappend because (presumably) the teacher has told students, “Here is how we might write append if it didn’t exist.”

                                                                                    Here’s the code formatted with more indentation (the right way)

                                                                                    Thank you, but that did nothing to make the code more readable to me. (See below on “to me.”)

                                                                                    subjective…Did you learn the cond macro? Minimal knowledge is required to read Lisp as with any other language.

                                                                                    I’m not sure, but you seem to be using “subjective” as a way of saying “wrong.” Or, to put this in another way, you seem to want to correct my (and Carl’s) subjective views. As a general rule, I don’t recommend that, but it’s your choice.

                                                                                    I’m glad you enjoy Lisp and find it productive. But you may have missed my point. My point was that I—and many people—do not find List readable or maintainable. (It’s hard to maintain what you find unpleasant and difficult to read, after all.) I wasn’t saying you or anyone else should change your subjective view; I was just stating mine. To quote jyx, “Yes, feeling is subjective and is fine.” I didn’t mean to pick on something you love. I was questioning how widely Lisp can play the role of great REPL plus readable maintainable programming language.

                                                                                    1. 5

                                                                                      hey, right, I now find my wording a bit rigid. My comment was more for other readers. We read a lot of lisp FUD, so sometimes I try to show that the Lisp world is… normal, once you know a few rules (which some busy people expect to know when they know a C-like language).

                                                                                      To merge two lists: use append.

                                                                                      rewording: “dear newcomer, be aware that Lisp also has a built-in for this”. I really mean to say it, because too often we see weird, teaching code, that does basic things. Before, these examples always bugged me. Now I give hints to my past self.

                                                                                      My point was that I—and many people—do not find List readable

                                                                                      OK, no pb! However I want to encourage newcomers to learn and practice a little before judging or dismissing the language. For me too it was weird to see lisp code at the beginning. But with a little practice the syntax goes away. It’s only syntax, there is so much more to judge a language. I wish we talked less about parens, but this holds for any other language when we stop at the superficial syntax.

                                                                                      or maintainable

                                                                                      but truly, despite one’s tastes, Lisp is maintainable! The language and the ecosystem are stable, some language features and tooling explicitly help, etc.

                                                                              1. 2

                                                                                The new text-davinci-edit-001 works pretty good.

                                                                                $ curl https://api.openai.com/v1/edits \
                                                                                  -H "Content-Type: application/json" \
                                                                                  -H "Authorization: Bearer $OPENAIKEY" \
                                                                                  -d '{
                                                                                  "model": "text-davinci-edit-001",
                                                                                  "input": "I drave to the stor3 to get egg, butt they had some.",
                                                                                  "instruction": "fix improper use of words",
                                                                                  "temperature": 0.3
                                                                                }'
                                                                                {"object":"edit","created":1675706759,"choices":[{"text":"I drove to the store to get egg, but they had none.\n","index":0}],"usage":{"prompt_tokens":34,"completion_tokens":42,"total_tokens":76}}
                                                                                

                                                                                Edit: apparently missed the egg.

                                                                                Edit #2: worked better after changing the instruction.

                                                                                curl https://api.openai.com/v1/edits \
                                                                                  -H "Content-Type: application/json" \
                                                                                  -H "Authorization: Bearer $OPENAIKEY" \
                                                                                  -d '{
                                                                                  "model": "text-davinci-edit-001",
                                                                                  "input": "I drave to the stor3 to get egg, butt they had some.",
                                                                                  "instruction": "Reword the sentence to fix any mistakes.",
                                                                                  "temperature": 0.3
                                                                                }'
                                                                                {"object":"edit","created":1675706966,"choices":[{"text":"I drove to the store to get eggs, but they had none.\n","index":0}],"usage":{"prompt_tokens":38,"completion_tokens":42,"total_tokens":80}}
                                                                                
                                                                                1. 1

                                                                                  Oh, interesting—I’ve been meaning to play around with the edit models more, especially because they’re in free beta. If they could be coerced into being sufficiently non-creative that could be a good alternative, have it edit the sentence and then highlight differences with suggestions.

                                                                                1. 1

                                                                                  Tag systems for contents retrieval is dying, just like web directories got replaced by search engines. The only use of tags will remain in social networks for short timed sensational usage.