[HN Gopher] Jackson structured programming
       ___________________________________________________________________
        
       Jackson structured programming
        
       Author : haakonhr
       Score  : 95 points
       Date   : 2021-08-12 11:26 UTC (1 days ago)
        
 (HTM) web link (en.wikipedia.org)
 (TXT) w3m dump (en.wikipedia.org)
        
       | CraigJPerry wrote:
       | This is referenced(1) as a core inspiration in the preface to
       | "How to Design Programs" but i never researched it further
       | because i've found the "design recipes" approach in htdp to be
       | pretty solid in real life problems.
       | 
       | 1. Analyse the problem and derive appropriate data
       | representations, write out illustrative examples
       | 
       | 2. Write a signature for the function - what does it consume and
       | what does it produce. Spend time to get a concise definition of
       | the computation it performs.
       | 
       | 3. Create some illustrative examples of what the function does
       | 
       | 4. Outline the function
       | 
       | 5. Fill in the gaps to complete the definition of the function
       | 
       | 6. Tidy up by converting some of those illustrative examples into
       | tests
       | 
       | There's a further practice to this of iterative refinement -
       | taking what you learn as you apply this process and use that info
       | to refine what you did.
       | 
       | This is a pretty solid way to go about things and it's utterly
       | trivial to bring a colleague up to speed with what you're doing
       | at any step when you need a hand. The biggest gap in practice of
       | this method that i've found is a lack of concern for efficiency.
       | It'd be fairly trivial to produce an n^3 solution following these
       | steps when an n solution exists.
       | 
       | I was always swayed by the "make it work, make it right, then
       | make it fast" approach before.
       | 
       | (1) ... Actually i just went and opened the book, the actual
       | reference is to Michael Jackson's method for creating COBOL
       | programs which is the progenitor of JSP.
        
         | DEADB17 wrote:
         | In the "Fundamentals"[1] course they use a table format for the
         | design recipe that makes the correspondence between data and
         | functions more obvious, and perhaps the JSP inspiration more
         | evident.
         | 
         | [1] https://course.ccs.neu.edu/cs2500f17/design_recipe.html
        
       | avinash wrote:
       | Read the book, which I obtained from the British Council library,
       | when I was around 15. I have to say that the book made quite an
       | impression on me at the time.
        
       | Zenst wrote:
       | I started out from a BTEC (changed to BECTEC and 2 years instead
       | of just 1 year shortly after I did mine) and was taught COBOL.
       | First Job doing COBOL and I wrote a program, really upset the
       | analyst - as with JSP exception handling done way differently
       | than just using GOTO (a COBOL verb I'd never used or was even
       | aware of as was hard core JSP). Was explained the whole aspect of
       | efficiency and with many aspects of code - what looks neat and
       | nice today over time will get modified and how it was easier to
       | modify something with GOTO's over some elegant JSP layout. That
       | and efficiency of the code - performance.
       | 
       | So I learned the usual lesson many do when you go from
       | Educational ideals into Working reality. Real World business
       | don't run on cutting edge changing soon as that changes,
       | legacy/stability and historical aspects do play out. So whilst
       | you may know a better way, there are many factors that make that
       | impracticable. Sure if rewriting your code-base and hardware to
       | the cutting edge of the time was viable then people would do it,
       | but testing and verification of code - when done properly takes
       | longer than the time to build the latest cutting edge system. Let
       | alone the whole cost factor.
       | 
       | I imagine many have comparable stories upon their move from the
       | realms of Education into Work. Do share as be nice to read what
       | brain-walls today's first workers encounter.
        
       | keithnz wrote:
       | this is how I was first taught how to design software. I found it
       | quite unnatural and didn't really use it. But it did help me
       | start thinking about how to structure software.
        
       | dustingetz wrote:
       | i believe this is equivalent to a modern functional effect
       | system, which compiles an AST (typically a hosted monadic sub
       | language, or equivalently a s-expression with control flow) into
       | a DAG intermediate language. The DAG is abstract and is then
       | further interpreted or compiled into an execution target, which
       | evaluate the DAG with late bound runtime properties like
       | asynchrony, exceptions, side effects, garbage collection,
       | structured concurrency. the key idea is that the DAG is abstract
       | and has no notion of the runtime behaviors like asynchrony;
       | structured programming is about capturing the computation's
       | essential structure as a DAG and then using that structure to
       | reflect the target runtime behavior. E.g. interpreting edges of
       | the DAG as callbacks. Structure is also about constraints (what
       | you can't or shouldn't do) and for example a DAG can't express
       | goto. But a DAG can express stack frames and lexical closures (by
       | nesting).
        
       | gerikson wrote:
       | I learned to plan programs with this.
        
         | pawal wrote:
         | Me too. Still have a couple of books (in Swedish) on the
         | subject. I don't have the heart to throw them away.
        
       | aidanr wrote:
       | I've just got "Structured Program Design Using JSP" off the
       | bookshelf. Haven't looked at it in about 30 years!
       | 
       | I was once sent on a work course to learn how to write COBOL
       | using Jackson Structured Programming. I _loathed_ it. I remember
       | thinking that
       | 
       | a) it tried reduce the programmers role to little more than that
       | of an automoton b) it was completely at odds with my views (30
       | years ago and still today) that good software development is a
       | blend of the technical and creative/artistic.
       | 
       | Happily very little of my working life involved actually using
       | JSP (well Java Server Pages excluded).
        
         | Zenst wrote:
         | Biggest erk and put-off many in COBOL had with JSP was
         | exception handling and with that - without using GOTO (which
         | was banned for JSP hardcore mentalities) you would end up
         | setting flags and having checks - adding a lot of processing
         | into the code-base at a time that was still before the IBM PC
         | was to come about. Even then, CPU's for large mainframes et
         | all, and the cost of CPU cycles and storage, sure did have a
         | far larger value than in later years.
        
           | danielnicholas wrote:
           | JSP used the "quit" statement to handle errors and
           | backtracking; it was a primitive form of exception before
           | exceptions were common. There's a lengthy defense of this in
           | the JSP book (on p.282) arguing that eliminating GOTOs
           | dogmatically is a mistake.
        
       | zdkl wrote:
       | Disclaimer: I have done exactly 0 research on JSP before today
       | and come from python/lisp land. Being in the middle of
       | developping an OpenAPI application with python's Pydantic (an
       | extension of type annotations), I can't help but feel python is
       | _this_ close to being a combination of JSP and data model
       | definitions. To go one step further if you write your modules
       | with Hy (a lisp that interops  & ~transpiles to python), you get
       | a pretty darn elegant codebase that is a rather direct mapping of
       | your domain problem to expressions which look a lot like these
       | JSP examples.
       | 
       | Maybe I'm only just discovering for myself the "power of typed
       | languages" (feel free to rib on duck typed devs here) but it
       | feels like a huge progress in terms of productivity, bug count
       | and readability. I love modern python.
        
       | danielnicholas wrote:
       | If you want an intro to JSP, you might find helpful an annotated
       | version [0] of Hoare's explanation of JSP that I edited for a
       | Michael Jackson festschrift in 2009.
       | 
       | For those who don't know JSP, I'd point to these ideas as worth
       | knowing:
       | 
       | - There's a class of programming problem that involves traversing
       | context-free structures can be solved very systematically. HTDP
       | addresses this class, but bases code structure only on input
       | structure; JSP synthesized input and output.
       | 
       | - There are some archetypal problems that, however you code,
       | can't be pushed under the rug--most notably structure clashes--
       | and just recognizing them helps.
       | 
       | - Coroutines (or code transformation) let you structure code more
       | cleanly when you need to read or write more than one structure.
       | It's why real iterators (with yield), which offer a limited form
       | of this, are (in my view) better than Java-style iterators with a
       | next method.
       | 
       | - The idea of viewing a system as a collection of asynchronous
       | processes (Ch. 11 in the JSP book, which later became JSD) with a
       | long-running process for each real-world entity. This was a
       | notable contrast to OOP, and led to a strategy (seeing a
       | resurgence with event storming for DDD) that began with events
       | rather than objects.
       | 
       | [0] https://groups.csail.mit.edu/sdg/pubs/2009/hoare-
       | jsp-3-29-09...
        
         | ob-nix wrote:
         | ... this brings back memories! In the late eighties I, as a
         | teenager, found a Jackson Struct. Pr. book at the town library.
         | I remember I was amazed at the text and wondered why I hadn't
         | heard about the method before.
         | 
         | If I remember correctly did the book clearly point out
         | backtracking as a standard method, while mentioning that most
         | languages lacked that, so it had to be implemented manually.
        
       | vjust wrote:
       | I tried to follow Jackson's book on Problem Frames, did not
       | complete the book, though I'd consider trying to read it again.
       | Its a non-formal or semi-formal methodology that emphasizes
       | understanding the structure of problems and domains before
       | solution design. Its a technique of architecture and systems
       | engineering.
        
       | aaronrobinson wrote:
       | I was taught this when working at British Gas in the mid 80s. I
       | remember this being followed by Delta 3GL which allowed you to
       | allocate code to the pre and post hooks etc of each node. Your
       | function 'places' were there and you just assigned code. It was a
       | very methodical way of working and IMO left less room for error.
        
         | Zenst wrote:
         | Did you also have to endure the era of `4GL` code generators
         | that would produce COBOL code and marketed shortly as would
         | make COBOL coders redundant?
         | 
         | I worked at Eastern Electricity Board in the early 80's - No
         | JSP there, but did work upon a new project that was object
         | focused - using COBOL - no data dictionary overkill project,
         | but saw what would normally be one program broken down into a
         | main body that would link in lots of functions - which in
         | themselves would be small contained COBOL programs. So one data
         | input screen would see a program for each field type, instead
         | of one large program and the main code would in effect be a
         | skeleton that would link in the screen template and needed
         | programs to handle those input/output data fields. Certainly
         | the way forward in many ways, though COBOL perhaps not the most
         | learning towards that.
         | 
         | I liked JSP, but then that was how I was taught COBOL in
         | education. Never really got to use it in anger due to legacy
         | standards and other factors which alas made sense unless your
         | doing greenfeild at the time.
        
           | mech422 wrote:
           | We had to endure 'synon' - a 4GL/rpg generator for the
           | AS/400.. When that thing fired up, it brought the whole
           | machine to its knees.
        
             | gjvc wrote:
             | https://www.youtube.com/watch?v=5pY6Xxptp9A
        
               | mech422 wrote:
               | LOL - thanks for the laugh!
        
           | aaronrobinson wrote:
           | Actually I think it was Delta 4GL. BACS built their payments
           | system using it. They put us in a warehouse basement in
           | Dunstable. That was a huge project. I wonder if they still
           | use it.
        
       | easytiger wrote:
       | This was actually taught as part of the a level in the school i
       | went to.
        
       | ChrisMarshallNY wrote:
       | Heh. I remember when the concept of subroutines was considered
       | dangerously subversive.
       | 
       | Structured Programming was thought of as revolutionary. Most
       | folks were either doing COBOL or Assembly, at the time. C was
       | just beginning to feel its oats (It was still thought of as a
       | mostly academic language, but it spawned a few languages that
       | were considered "workhorse" languages, like PL/1).
       | 
       | I did start using Pascal, in the 1980s, because that was Apple's
       | native language. It was a very strange language, coming from
       | Assembly, FORTRAN, BASIC, and PL/1.
        
         | cross wrote:
         | PL/1 definitely predates C.
        
           | ChrisMarshallNY wrote:
           | Ah. That makes sense. I always assumed it was one of many
           | derivative languages.
           | 
           | I wrote a tool or two, in PL/1.
        
           | mech422 wrote:
           | I have really fond memories of working on Stratus VOS and
           | PL/1. Those machines were FUN :-D
        
       | ithkuil wrote:
       | I have to admit that when I first heard the Jackson reference in
       | https://youtu.be/HxaD_trXwRE?t=00m44s I thought it was about the
       | other Jackson.
        
       | donatj wrote:
       | There's an old Rob Pike talk where he asks the audience:
       | 
       | "So how many of you are familiar with the work of Michael
       | Jackson" Most of the crowd raises their hand to which he replies
       | "Really? Quite a few! Well as you know, Michael Jackson developed
       | Jackson Structural Programming".
       | 
       | He was seemingly unaware of the popstar of the same name.
       | 
       | - https://www.youtube.com/watch?v=HxaD_trXwRE&t=44s
        
         | butterisgood wrote:
         | Also the beer hunter. http://www.beerhunter.com/
        
           | azinman2 wrote:
           | Michael Jordan is the name of a famous AI/ML researcher. What
           | I love is they're both tops of their careers.
        
         | elwell wrote:
         | I fairly certain he was telling a joke. Hence the "well as you
         | know" lead in.
        
           | LukeShu wrote:
           | It's been a long time since I watched that talk, but I seem
           | to remember that about 40 minutes in he has a moment where he
           | remembers that there's another Michael Jackson and apologizes
           | for the confusion.
        
       | dkarl wrote:
       | > In Chapter 3 of Principles of Program Design[1] Jackson
       | presents two versions of a program, one designed using JSP, the
       | other using the traditional single-loop structure.
       | 
       | I think I've come back around to seeing some merit in the
       | "traditional" version. All the state is declared before the main
       | loop. You could stop the program after any iteration of the
       | single loop, save the explicitly declared state, and restart
       | where you left off. The logic inside the loop can be applied to
       | any record and state.
       | 
       | In the double-loop version, your place in the control flow is
       | part of the state. If you stopped, you wouldn't know where to
       | start up again. There's also a state variable (firstLineOfGroup)
       | declared inside the loop.
       | 
       | I know why I prefer the "traditional" version: it can easily be
       | refactored to be functional, and making the state explicit means
       | it doesn't have to be refactored if I want to store the state
       | externally or switch from a batch architecture to a streaming
       | architecture. The JSP version is inherently imperative and needs
       | to be refactored before it can be used in a different
       | architecture. Funny how ideas like that alter your taste.
        
         | [deleted]
        
         | nyanpasu64 wrote:
         | I think coroutines, generators, and async allow the compiler to
         | transform the two-loop version into a state machine that can be
         | suspended at a readLine() or println() call.
        
           | dkarl wrote:
           | A compiler that could take the JSP version and transform it
           | into a streaming job with managed state would be pretty cool.
           | Otherwise, a programmer has to construct the streaming
           | architecture around the code, whether they integrate it into
           | an existing framework like Flink or write all the state
           | handling and management themselves. In that case the
           | processing code has to be structured so that the state is
           | explicitly passed in and out for each record.
        
             | scott_s wrote:
             | Or use a language with generators and coroutines? I believe
             | this would be natural to express in Python and (maybe) with
             | C++20's coroutines. Java's stream API could also probably
             | accomplish something similar.
        
             | [deleted]
        
             | danielnicholas wrote:
             | That's exactly how JSP was used. In its first application
             | to COBOL, the JSP-COBOL tool turned structured code into
             | coroutining code with suspend/resume, and tools built later
             | for JSD generated code to save state in a database.
        
         | danielnicholas wrote:
         | My experience is that when people write the "traditional
         | version" they often get it wrong.
         | 
         | For your amusement, here are two version of a function to split
         | a string into words, one in JSP style, and one in "traditional
         | style" that actually appeared in a conference talk a few years
         | ago by a very famous computer scientist (translated into JS to
         | provide him with some anonymity :-). I think they're both
         | "correct" but in my view the JSP one is easier to understand.
         | // JSP version of a split function         split_jsp = function
         | (s) {           words = [];           i = 0;           while (i
         | < s.length) {             while (is_white (s[i]))
         | i++;             word = "";             while (is_alpha (s[i]))
         | word += s[i++];             if (word.length > 0)
         | words.push(word);             }           return words;
         | }                // "traditional" version of a split function
         | split_traditional = function (s) {           words = [];
         | word = "";           for (i = 0; i < s.length; i++) {
         | ch = s[i];             if (is_white (ch)) {               if
         | (word != "") words.push (word)               word = "";
         | }             else               word += ch;             }
         | if (word != "")             words.push (word);           return
         | words;           }              is_white = ch => (ch == ' ' ||
         | ch == '\t' || ch == '\n')         is_alpha = ch => ch !=
         | undefined && (/[a-zA-Z]/).test(ch)
        
         | [deleted]
        
       | zetalyrae wrote:
       | For such a young discipline, it's amazing how much of software
       | practice used to be standard operating procedure and is now all
       | but forgotten.
       | 
       | At one time Dijkstra had to actually _argue_ for structured
       | programming. No-one would take the counter position today.
       | 
       | The equivalent debate nowadays is between languages that separate
       | statements and expressions and expression-oriented[0] languages.
       | 
       | [0]: https://en.wikipedia.org/wiki/Expression-
       | oriented_programmin...
        
         | TeMPOraL wrote:
         | Is that really a debate? Gosh, I'd love to see the "separatist"
         | arguments, because ever since I've discovered Lisp, I've
         | automatically assumed that separating statements and
         | expressions is one of those stupid historical baggage things, a
         | stepping stone in early PL design that we can't just get rid
         | of.
         | 
         | I mean, how many libraries with weird APIs were created just
         | because you can't write the following in most Algol-like
         | languages:                 return if(sth) {                 foo
         | = SomeProcessing();                 Transform(foo);
         | } else if(sthelse) {                 Transform(someDefault);
         | } else {                  someErrorDefault;              };
         | 
         | In many languages, people are resorting to "immediately invoked
         | function expressions" to simulate this pattern (whether for
         | returning or assigning). And those that can't, well, here goes
         | another pointless little function to encapsulate it[0].
         | 
         | --
         | 
         | [0] - Which transitions into what is a real debate - "lots of
         | small functions" vs. "fewer but larger functions". It's one of
         | those holy wars that can't die, because both sides have good
         | arguments. But it's a false choice - a limitation of the tools
         | we're using to write programs. 'emilprogviz has a nice summary
         | of that last point here:
         | https://emilprogviz.com/ep05/ep05-transcript.html
         | 
         | Linking to transcript, in the spirit of "text with screenshots
         | is almost always better than a video" - (nice job providing it
         | Emil!) - but the video itself is good too, as are others on
         | that site.
        
           | zetalyrae wrote:
           | Ok it may not exist as a debate outside my own head :)
           | 
           | To offer one argument: the problem with expression oriented
           | languages is their generality, in that you can write "weird"
           | expressions, e.g.:                 let x =         [giant
           | block of code with multiple nested lets, ifs, etc.]       in
           | f(x)
           | 
           | I've definitely done this a number of times. Languages that
           | separate statements and expressions force you to break things
           | down further and prevent the code from going too far to the
           | right.
           | 
           | Also, for low level languages, the mapping between code and
           | assembly is clearer in languages that separate statements and
           | expressions (I need a more succinct term).
           | 
           | EDIT: Also, by preventing statements from being used as
           | expressions, you encourage breaking up long and complex
           | statements into smaller functions.
        
             | TeMPOraL wrote:
             | > _in that you can write "weird" expressions_
             | 
             | Oh, I see what you mean. I discovered Lisp after working in
             | C++ and Java, so I avoided this pitfall in my code, but if
             | I had a dollar for every instance of:                 (let
             | ((some-variable (progn                               (do
             | stuff)                               (do other stuff)
             | (let ((some-helper-var ...))
             | (some more code with some-helper-var)             (more-of-
             | the-same (progn                                  ...)))
             | ;; 50-100 lines later, just return one of the values
             | some-variable)
             | 
             | that I saw in Lisp codebases, particularly in Emacs,
             | well... I could feed my family for a month or two from that
             | money.
             | 
             | There's plenty of abuse potential here (and for the love of
             | god, if your language has 'let', it probably also has
             | lambdas or 'flet', use that to create local functions...).
             | But mitigating this, arguably, is a problem for style
             | guides - the overall feature of "everything is an
             | expression" is powerful. It has nice simplicity to it, and
             | reduces boilerplate :).
             | 
             | > _Also, for low level languages, the mapping between code
             | and assembly is clearer in languages that separate
             | statements and expressions_
             | 
             | I'm guessing this is where the separation originally came
             | from. Assembly is essentially statement-only. But at this
             | point, I think all programming languages in use crossed the
             | threshold where we're actually programming to an "abstract
             | machine", and being expression-oriented seems to confer
             | greater expressiveness.
             | 
             | > _(I need a more succinct term)._
             | 
             | "Separatist"? :).
             | 
             | > _EDIT: Also, by preventing statements from being used as
             | expressions, you encourage breaking up long and complex
             | statements into smaller functions._
             | 
             | Ah yes. The real debate. I edited my comment to mention it
             | before I saw your edit :).
        
               | zetalyrae wrote:
               | Yes, thank you, your code example is much better than
               | mine.
               | 
               | The simplifying potential of expression-oriented
               | languages is huge. Alan Perlis said[0]: "symmetry is a
               | complexity-reducing concept; seek it everywhere", and
               | this is a great example of that.
               | 
               | For example, languages like C and Ada have both if
               | statements and if expressions, this is a duplication that
               | can be eliminated by making them expression-oriented so
               | you only have an if expression like in Haskell or ML.
               | 
               | But, interestingly, there is one historical case of a
               | language going from expression-oriented to
               | statement/expression separation: ALGOL-W[1] was
               | expression oriented, Pascal[2], its successor, separates
               | statements from expressions. Wirth designed both.
               | 
               | I don't know what the motivation was, but I suspect it's
               | because Pascal was designed to be an educational
               | language, and Wirth must have thought that separating
               | expressions and statements made didactic sense when
               | teaching programming as a recipe or list of things to do,
               | as opposed to the more mathematized formulation of
               | expression-oriented languages (of having an evaluation
               | function from expressions to values).
               | 
               | The successors of Pascal (Ada, Modula and its sequels)
               | retain the statement/expression separation.
               | 
               | [0]: http://pu.inf.uni-
               | tuebingen.de/users/klaeren/epigrams.html
               | 
               | [1]: https://en.wikipedia.org/wiki/ALGOL_W
               | 
               | [2]: https://en.wikipedia.org/wiki/Pascal_(programming_la
               | nguage)
        
               | tangus wrote:
               | I can't say for sure, but I suspect it was a reaction to
               | ALGOL-68. Creators of later Algolish languages usually
               | made a point of rejecting features of Algol-68 they saw
               | as prone to abuse.
               | 
               | And the block expressions in Algol-68 were certainly used
               | and abused. Basically, the type and value of a block
               | (BEGIN ... END or ( ... )) are those of its last
               | expression, so you can put them anywhere. For example,
               | Algol-68 has the looping construct WHILE <condition> DO
               | <body> OD, but not C's `do <body> while (<condition>)`.
               | So what do you do if you want to have the test at the end
               | of the loop body? Simply                   WHILE (
               | <body>;            <condition>            )         DO
               | SKIP OD
               | 
               | I guess you'd get used to those idioms eventually, or
               | some coding conventions would have arisen if the language
               | had been successful. But I can understand language
               | creators looking at that and seeing how getting rid of it
               | simplifies not only their compilers but also the programs
               | written in their languages.
        
               | Wildgoose wrote:
               | What is wrong with simply:                 test := True;
               | WHILE test       DO          <body>;          test =
               | <condition>       OD
        
               | chalst wrote:
               | That introduces a variable that has to be initialised
               | outside the control block. It's not terrible as hacks go,
               | but I guess the readability cost of the additional
               | variable is higher than having the body in the condition.
        
               | tejtm wrote:
               | standard practice "Sentinel value" when I was a student
        
               | Wildgoose wrote:
               | Agreed, but it also allows for a more sophisticated
               | <condition> testing to take place within the body of the
               | loop.
        
               | tangus wrote:
               | Nothing is wrong with it, but your suggestion comes 40
               | years too late. The popular idiom was the one I
               | mentioned.
        
               | memling wrote:
               | > Oh, I see what you mean. I discovered Lisp after
               | working in C++ and Java, so I avoided this pitfall in my
               | code, but if I had a dollar for every instance of: [...]
               | 
               | This is one of those anti-patterns I sometimes find
               | myself falling into (I don't code Lisp or its descendants
               | often). It's kind of discouraging, to be honest, because
               | it feels like there ought to be some more efficient way
               | to do this, and my inner critic comes along and complains
               | that I'd be better of writing Python or C than learning
               | to do it the Right Way in Lisp.
               | 
               | Is there some kind of idiomatic way to avoid this and
               | write cleaner code? Is the solution to simply extract the
               | progn into another function? Does that violate some rules
               | of function encapsulation in Lisp?
        
               | zetalyrae wrote:
               | I think extracting functions is the way to go. I like it
               | when a function's body reads like a sentence, when it's
               | been broken down to the atoms of that conceptual level of
               | abstraction. Forth code that achieves this can look very
               | satisfying.
               | 
               | The problem is that the toplevel of a module is full of
               | functions at various levels of granularity.
               | 
               | It might be nice if programming languages had a concept
               | of "code sections" (you could implement this with
               | literate programming), where modules are organized
               | hierarchically into sections, and declarations can be
               | public or private within a section. So you might have:
               | section foo         // Accessible from outside this
               | section         public important_function()
               | // Only accessible from inside this section
               | private utility_function_1()              private
               | utility_function_2()       end section
        
               | memling wrote:
               | > The problem is that the toplevel of a module is full of
               | functions at various levels of granularity.
               | 
               | Exactly--this is what I was hinting at with "rules of
               | function encapsulation." I took a course on LISP in
               | college (apropos of nothing, it featured a lab called,
               | "Isn't this just a one credit course?") in which it
               | seemed like the LISP Way was to use helper functions.
               | It's always felt like something was missing in my ability
               | to "translate" between paradigms because this rubs me the
               | wrong way (although as I went through some examples I
               | realized I do this with some regularity in other
               | languages--but it doesn't "feel" as bad).
               | 
               | In retrospect probably part of the problem was that we
               | ALGOL-adjacent undergrads didn't have the scaffolding to
               | understand more generic approaches like fold and cousins.
               | It was a different way of thinking.
               | 
               | I like the idea of literate programming as a potential
               | solution, especially as it can be used to guide newbies
               | through the code and identify areas where idioms are much
               | different between one's existing paradigms and that of
               | the codebase.
        
               | zetalyrae wrote:
               | In Common Lisp you can use FLET or LABELS to declare
               | local functions. This works, but there really is no good
               | solution: utility functions often just take up space and
               | belong nowhere.
        
           | lmilcin wrote:
           | The issue with these debates is that these tend to be driven
           | by people with strong opinions coming usually from
           | misunderstanding of the other side of the debate.
           | 
           | I like to think that there is no OOP vs FP, there is no
           | strong typing vs no typing, there should be just adding to a
           | shelf with tools that each has application in some situations
           | but also constraints on when it can be used effectively. And
           | your job as developer is to understand the bounds on
           | application and effectiveness.
           | 
           | The road to mastery of development then should be by learning
           | and understand those various tools (in the broadest possible
           | sense) rather than by forming strong opinions and shunning
           | the other side of the debate. People who cut off themselves
           | from OOP will never learn its benefits just as people who cut
           | themselves from FP.
        
           | ratww wrote:
           | I think the "separatist" side (yep I'm adopting your term)
           | has already accepted that the war is lost, but I still see
           | battles being waged often in programming language spec
           | committees, whenever there's a suggestion for allowing if to
           | be treated as an expression.
           | 
           | The arguments against it are always that it requires having
           | keywords that behave differently when being expressions or
           | statements.
           | 
           | Often the alternatives and compromises proposed always have
           | the same issues, such as Javascript repurposing the _do_
           | keyword for enclosing expression ifs.
        
             | ItsMonkk wrote:
             | The intuition that I've built up is that most of the time
             | that you have a debate that goes on for more than about 5
             | minutes, there's a problem at a different abstraction
             | level.
             | 
             | For instance with Imperial vs Metric System, Metric
             | optimizes for multiplication, while Imperial optimizes for
             | division. You can never unify these under the current
             | system. But you can, if you change our base to base 12.
             | Then they suddenly merge.
             | 
             | With CLI vs GUI, we've realized that we needed a mixture.
             | We need a GUI that runs through a CLI. And now we have
             | that, it's called a website. I think tabs vs spaces was
             | solved similarly, with tabs as spaces that editors config
             | can treat n-straight-spaces as tabs.
             | 
             | I'm firmly on the expression only and lots of functions
             | sides, but that transcript is very interesting. You can
             | already do local functions in C#, it seems to be implying
             | that we should strive for that to be our mixture.
        
           | kragen wrote:
           | Well, I'm not sure I'm on one side or the other of the
           | statements-or-no-statements debate, but in general I think
           | the argument in favor of separating statements from
           | expressions is that it adds redundancy to your programs,
           | which makes them easier to read and enables the compiler to
           | produce better error messages when you have a syntax error.
           | Sometimes you can trade this off against other aspects of
           | syntax you'd like to improve; Lua, for example, omits
           | semicolons and isn't white-space sensitive, but the compiler
           | can still emit reasonable syntax error messages because of
           | its strict separation of statements and expressions.
           | 
           | I think you're overstating the case with
           | return if(sth) {                 foo = SomeProcessing();
           | Transform(foo);              } else if(sthelse) {
           | Transform(someDefault);              } else {
           | someErrorDefault;              };
           | 
           | You can transform this to the following in even the most
           | limited ALGOL-like languages, which is less clear but not
           | nearly as heinous as the alternatives you mention:
           | var rv: SomeType;  -- return value         rv =
           | someErrorDefault;         if(sth) {            foo =
           | SomeProcessing();            rv = Transform(foo);         }
           | else if(sthelse) {            rv = Transform(someDefault);
           | }         return rv;
           | 
           | The more popular ALGOL-derived programming languages like C,
           | Java, and post-walrus Python have conditional expressions and
           | assignments inside expressions, which means that in this case
           | you don't need to resort to declaring a variable. In Golang
           | and Pascal you can just assign to the named return value
           | rather than declaring it as a normal variable and then
           | explicitly returning it.
           | 
           | The argument _against_ separating expressions from statements
           | is _also_ that it adds redundancy to your programs, as in the
           | above example.
           | 
           | I wrote an essay about this tradeoff in general, not limited
           | to expressions vs. statements, at
           | http://www.paulgraham.com/redund.html.
        
         | valyagolev wrote:
         | von Neumann was angry at a student for writing a program that
         | would produce binary code rather than assembling it by hand
         | 
         | https://twitter.com/sigfpe/status/1420961392585154569
        
           | TeMPOraL wrote:
           | Oh, the brief time in computing history when computer time
           | was more expensive than human time.
        
             | valyagolev wrote:
             | highlights the point that not valuing either will waste
             | both
        
             | microtherion wrote:
             | If you take into account that the particular humans whose
             | time was (not) valued here were _graduate students_ , that
             | time may not have been so brief after all.
        
           | scott_s wrote:
           | _WOW_. J.A.N. Lee taught my intro to programming in C++
           | course back in  '99. He retired during my undergrad.
        
           | lou1306 wrote:
           | I mean, it sounds weird _now_ , but back then the assembler
           | would indeed have eaten up precious CPU time.
           | 
           | Imagine if, nowadays, a grad student took a node in a
           | scientific cluster to run Dreamweaver in a Windows VM instead
           | of writing HTML by hand. (Sorry, it's the closest analogy I
           | could come up with)
        
             | zetalyrae wrote:
             | von Neumann was probably the most intelligent person ever
             | documented.
             | 
             | He was probably frustrated that people couldn't see the
             | machine code fully formed in their mind's eye :)
        
               | runlaszlorun wrote:
               | Agreed! I also think that von Neumann (and some of his
               | contemporaries as well) were likely the last to be able
               | to understand the entire breadth of math, physics, and
               | computer science at the time. These days we're all far
               | too specialized...
        
         | AnimalMuppet wrote:
         | No, I don't think that's the equivalent debate today.
         | Structured programming vs "the old way" was about clarity of
         | control flow. Structured programming was clearly superior once
         | you had machines with enough muscle to handle the overhead.
         | (And once you realized that you were trying to optimize for
         | programmer time rather than for machine time.)
         | 
         | I don't see expression-oriented as being similar to that at
         | all. Expression-oriented may provide a boost to programmer
         | efficiency, but it's not nearly on the order of structured
         | programming vs. unstructured. It doesn't require changing
         | peoples' mindset to realizing that programmer time is more
         | valuable than machine time; they already know that. And, the
         | parallel problem would be clarity of data flow, and I'm not
         | sure that expression-oriented is a huge win in that area.
        
       ___________________________________________________________________
       (page generated 2021-08-13 23:01 UTC)