[HN Gopher] Software Mimicry
___________________________________________________________________
Software Mimicry
Author : BobbyVsTheDevil
Score : 58 points
Date : 2022-11-19 02:35 UTC (20 hours ago)
(HTM) web link (www.hillelwayne.com)
(TXT) w3m dump (www.hillelwayne.com)
| arh68 wrote:
| So are the birds mimicking the bees, or is it the other way
| around? Maybe I'm just missing the point.
|
| I mean, is int[] a mimic of ArrayList<Integer>, or vice versa? Of
| course they're similar, of course they're different. Is "mimicry"
| just a pejorative thing?
| Smaug123 wrote:
| A definition is given as literally the first paragraph of the
| post.
|
| > Mimicry is when software X reimplements at a higher level a
| core feature of software Y. The produced facsimile has some,
| but not all, of the same properties, enough to "look like" it's
| the same thing but missing many of the nuances. This exists in
| every kind of software. One language can mimic another, a
| library can mimic a language, a database engine can mimic a
| product, etc.
|
| I don't see how your question even fits into that definition.
| LAC-Tech wrote:
| _In Design Patterns in Dynamic Programming, Peter Norvig notes
| that strategies are just trivially replacable with higher-order
| functions (HOFs)._
|
| So that's where this trope is from! A few things:
|
| 1. The "just replace it with a higher order function" thing
| obviously falls apart when your strategy has multiple methods. In
| which case, the FP programmer might be tempted to supply a record
| where each field is a function, and maybe they want to close over
| some shared implementation details and... you've just re-invented
| objects, albeit memory in-efficient ones.
|
| 2. In many languages that support OO, a higher order function
| _is_ an object, same way a string is, or an Integer.
|
| I might be being harsh here. Presumably Norvig wrote this in the
| hey day of "OO flavoured" languages like C++ and Java being
| completely dominant in industry. But in 2022 we can stop
| repeating this tired trope.
| Smaug123 wrote:
| Isn't your point 2 exactly what OP said?
|
| > I think it's more interesting to think of the GoF-language as
| mimicking HOFs with the strategy pattern facsimile. The
| strategy pattern reimplements HOFs as a code-level idiom.
| LAC-Tech wrote:
| No more than HOFs are mimicking objects.
|
| It's two schools of thought - everything is functions & data,
| or everything is objects & methods.
| zasdffaa wrote:
| Closures are implemented as objects under the skin, but
| that doesn't make them equivalent conceptually to me. I
| suppose it's down to syntax, after all if you ignore that
| you can have anything you like in assembler, but it won't
| feel very high level.
| layer8 wrote:
| Closures are a poor man's objects. Objects are a poor
| man's closures.
| zasdffaa wrote:
| What's the "poor man's" stuff? Is there a better way I
| don't know of
| Jtsummers wrote:
| https://wiki.c2.com/?ClosuresAndObjectsAreEquivalent
|
| Comes from that koan.
| spinningslate wrote:
| Enjoyed this, as with most of Hillel Wayne's writing. One bit
| that puzzled me:
|
| > "Representation" is similar to mimicry, except it's about
| encoding a data structure in primitives that aren't well-suited
| to it. Examples would be representing a tree in SQL tables,
| representing a matrix with nested arrays, or representing a graph
| in json.
|
| I can see the first two exampples (tree in SQL, matrix as nested
| arrays) because there are limitations in the representation. The
| last one though (graph in json) doesn't seem obviously limited.
|
| Mathematically, a graph G=(V, E), i.e. a set V of vertices
| (nodes) and a set E of edges between nodes. That has a direct
| translation into json: { "G": {
| "V": ["v1", "v2", "v3"], "E": [["v1", "v2"],
| ["v1", "v3"]] } }
|
| Perhaps it's that each edge is encoded as a list? Or that lists
| aren't sets, so there might be duplicates? Enlightenment
| appreciated.
|
| --
|
| EDIT: fixed typo.
| rzzzt wrote:
| They are probably alluding to the tree-like structure of JSON
| where you can't represent cycles without inventing a pointer +
| identifier format first, and that is indeed not part of the
| building blocks "JSON-the-language" itself provides.
|
| This seems to be a direct continuation of the SQL example --
| wouldn't you be able to represent a tree with eg. tree paths
| stored for each item?
| tomwojcik wrote:
| Emphasis on "aren't well-suited to it", I guess. It gets
| complicated once you want to parameterize each node.
|
| For the past year or so I've been "typing graphs" into YAMLs.
| It's definitely doable, but hard to follow, especially with
| cyclic graphs.
|
| N8N is a very popular nocode workflow builder with a great UI.
| They store workflows (graphs) as JSON. I use this complicated
| workflow https://n8n.io/workflows/1534-back-up-
| your-n8n-workflows-to-... in my homelab but I can't find a
| public JSON representation of it. It'd be a great example of
| how to present a complicated graph. I'll add it as an edit if I
| find it.
|
| EDIT: I found one public workflow backup on github.
| https://raw.githubusercontent.com/thethanghn/n8n-workflows/d...
|
| It's not that bad.
| enriquto wrote:
| > That has a direct translation into json:
|
| Sure, but this representation is horrific, and a very clear
| example of why json is not the appropriate format to store
| graphs. A more natural format for graphs would replace your
| punctuation-ridden monstrosity with a simple text file, for
| example: v1 v2 v1 v3
| spinningslate wrote:
| I take your point, though you're not directly comparing like
| with like. I'd used a literal translation of (V, E) so listed
| vertices explicitly as well as edges. Using implicit
| representation (as you have), the json could be simplified to
| [["v1", "v2"], ["v1", "v3"]]. Still more syntax, definitely.
| But not far off, for example, the graphviz[0] equivalent in
| syntax overhead terms: graph {
| v1 -- v2; v1 -- v3; }
|
| To be clear, I'm no apologist for json. It just seemed to me
| there was a pretty direct representation. @rzzzt's
| observation on json being predominantly hierarchical and
| therefore tree-shaped seems like the most likely reason
| behond the original statement.
|
| --
|
| [0] http://graphviz.org/
| reuben364 wrote:
| For the StrategyWithSetup example, my FP oriented brain would
| create another function: withSetup :: IO c ->
| IO d -> (a -> IO b) -> a -> IO b withSetup mc md f = \ a
| -> do mc b <- f a md
| return b
|
| Which is pretty identical except with a closure over functions in
| place of a class of abstract methods. Classes with abstract
| methods are effectively higher order functions, except
| differences in boilerplate.
|
| Another thing worth mentioning are language features that can't
| be implemented unless you effectively implement a DSL like
| automatic differentiation, call-cc, algebraic effects.
|
| Hooks in React are sort of like a poor man's algebraic effects.
| It can't affect the control flow so it relies on immutability and
| hooks to unconditionally run to operate.
|
| EDIT: after a bit of thinking, I realize that the unconditional
| ordering of hooks is really a way to identify call sites at
| runtime, which I don't think is related to algebraic effects.
| samsquire wrote:
| I called this idea of deliberately applying software mimicry as
| branching libraries in my ideas document (link in profile (the
| first link))
|
| I experiment with programming language theory and designs as a
| hobby and one of my thoughts is that the core underlying problem
| of computing is an arrangement problem of a turing machine.
| Compiling is "planning what you shall do". Execution is "doing".
| We have the luxury of many ways of doing things in computing. But
| it all seems to lead to mess of poor understandability and
| complexity.
|
| We're still trying to find the best way of doing things.
|
| What am I trying to say? OOP inheritance hierarchy trees are
| limited and not what you really want to do to represent your
| problem. I want to define a situation or scenario and define what
| should happen in that scenario. This is where asynchronous
| programming and join calculus shines. I also like occam-pi's
| select statement and golang's select. I also feel every computing
| problem is the "expression problem" manifested. How do you
| associate behaviour (what to do) with a type (a situation)? And
| how do you define them so you don't have to reimplement all the
| previously existing behaviours with the new thing?
|
| The next section shall be reductive.
|
| Ultimately all loops, function application, methods, expressions,
| variables, classes, functions, lists, vectors, data structures,
| algorithms exist as "things" in the imagination of the
| developer's mind and the compiler. They don't exist in machine
| code.
|
| We have a grid of memory locations and the arrangement of things
| in that grid is handled by a memory allocator. We also have
| references in this grid as pointers, which form a structure of
| their own. A turing machine.
|
| Thinking of a type and behaviour as being solely one thing only
| at a time is inherently limiting. I often want to see different
| things "as" something else to talk about them in a slightly
| different approach. A vector or ArrayList of objects of multiple
| types but processed in the same approach, efficient compile time
| polymorphism.
|
| This is kind of how I imagine object orientated development to
| really be about, I want to be capable of referring to an
| arbitrary selection of objects and define new behaviours or
| relations between the objects. Unfortunately most OOP ties
| imperative behaviour and stateful manipulation to data rather
| than modify exhibited behaviours of objects. Imagine being
| capable of organising and managing load balancers and draining
| them and devops architecture with code. A point and click GUI
| where I can right click a load balancer and click drain. (I don't
| mean code to bring them up or create them but to actually
| administrate them with OOP)
|
| I think the expression problem is a core problem of modern
| computing and doesn't have an efficient solution.
|
| We can decouple data structure, layout and algorithm.
| Unfortunately most programming languages couple data structure +
| layout (C) and OOP languages couple algorithm with layout.
| Functional programming languages I'm not sure about.
|
| I've been working with C++ templates recently with C++20
| coroutines and multithreading and I am finding template
| instantiation very interesting. I've been late to come around to
| it.
|
| This comment mentioned the insight that boxing and template
| instantiation are related.
| https://news.ycombinator.com/item?id=14764780
|
| I am also working on a multithreaded programming language which
| looks similar to Javascript. I use an actor implementation that
| can send messages between threads.
|
| https://github.com/samsquire/multiversion-concurrency-contro...
|
| One of my programming language designs is the idea that every
| line of code is a concurrent process and data flow is scheduled
| by topological sorting. Iteration is handled automatically for
| you. Every variable is actually a relation and algebraic
| definition of relations between processes. This is called
| algebralang. https://github.com/samsquire/algebralang
|
| The idea is that you write the underlying insight into the
| problem as an expression of what you want to do and let the
| computer schedule the ordering or arrangement of operations to do
| it. It's a form of pattern matching on the state of things
| (objects in the system) and declaration of the desired result.
| This brings to mind the rete algorithm (expert systems) and
| differential dataflow.
___________________________________________________________________
(page generated 2022-11-19 23:01 UTC)