In linguistics, we have "denotation" and "connotat...
# thinking-together
i
In linguistics, we have "denotation" and "connotation" as two forms of meaning. In programming, we have denotational semantics and operational semantics. Do we have connotational semantics? (If not — may we?)
p
We have idioms and design patterns which, when recognized by a reader, carry connotations. Whether that's a good thing or a bad thing is debatable. Paul Graham has argued that the presence of design patterns in a language indicates an inability to create the abstraction you really need. For example, he has compared design patterns to manual macro expansions. https://twitter.com/paulg/status/1409386827803410436 Peter Norvig is rumored to have said "Design patterns are bug reports against your programming language." He also pointed out how many standard design patterns become unnecessary in a sufficiently dynamic language. https://norvig.com/design-patterns/
i
My sense is that every (say) adjective in human language both denotes and connotes distinct meanings. Does every programming construct connote something? Is this where the debate over the meaning of reduce vs loop emerges?
p
My first instinct is to say the connotation is (ideally) the programmer's intent. I'm not certain yet whether I believe that, but starting from there... I think this does seem relevant to discussions about language features specifically meant to iterate over a range of numbers or the members of a collection, versus something more generic like the for loop in C. One could argue that the distance between denotation and connotation is greater with a generic for loop than it is with a loop structure specifically meant to iterate over the members of a collection, and by reducing the difference between denotation and connotation you reduce the intellectual difficulty of reading the code, and you make it easier for the compiler to infer the programmer's intent for purposes of optimization.
i
I'd go further — I think there's a bit of a low-brow stink on using a for loop when (say) mapping would be more elegant, and (right back at them) a bit of a high-brow stink on anything fancier than a loop. Like, our programming constructs have a culture around them. The choice of construct connotes something about the person who wrote the code.
(A word can connote more than one meaning simultaneously, right?)
p
Of course. I'm not a literary type, but I think that's where many of the so-called layered meanings in literature and poetry come from.
i
So perhaps the connotational semantics are tied up with the reasons that a construct is added to a language.
p
And a word can definitely denote more than one meaning simultaneously. That's where puns come from!
So perhaps the connotational semantics are tied up with the reasons that a construct is added to a language.
That might be where some of them start, but I think connotations, like idioms, grow within the shared understanding of a community.
Disclaimer: I've given this no serious thought before, so I may have totally different opinions tomorrow.
j
I definitely think different language constructs carry connotations. Don’t know any work specifically about it. But am reminded of this I saw the other day. https://interconnected.org/home/2023/12/05/code
e
Barthes! For Barthes connotation and denotation are different orders of “signification.”
He suggested that the construction of myths results in two levels of signification: the “language-object”, a first order linguistic system; and the “metalanguage”, the second-order system transmitting the myth.
Where the language-object refers directly to some thing, and metalanguage is used to convey meaning in the mode of myth!
(this is sort of foundational to a lot of marxist readings of stuff, so…a marxist programming?)
a
Ivan, were you ever a Rubyist? I was, in the early 2000’s when there were dozens of DSLs for any particular task, and the various sources of connotation described in this thread were in full force—syntactical, tribal, brow-based. Whether and when you chose to write { and } or “do” and “end” (which are basically equivalent) could make me feel at home in a file or like a foreigner, because it said something about who you learned Ruby from or which language you just came from. It probably wasn’t a special time or language, but it’s something I noticed because I was in a community that reveled in it.
i
Yeah, that's a great example of what I'm thinking.
p
Not sure exactly what the different styles connote, but there used to be holy wars over indentation styles. https://en.m.wikipedia.org/wiki/Indentation_style http://www.catb.org/jargon/html/I/indent-style.html Perl has an especially idiom heavy culture. I still remember thinking through "do_something(..) || die(...);" the first several times I saw it. I once worked on a code base where the standard way of doing something i times was "while(i--) {...}". THAT took some getting used to.
a
I love this question. I’m still thinking about it. I thought of a few mundane examples of when designers intentionally smuggled connotations into the language: “foo!” as syntax for unsafely removing null from foo’s type, and “foo?.bar” for when we’re unsure whether foo exists. These are good. But man, I can’t think of instances as universally relatable as we have in prose. Like syntax for begrudgingly implementing an interface, or timidly asserting a precondition, or sarcastically implementing a can’t-happen branch, or apologetically throwing an exception. I can’t think of a way, without a comment, to tell a reader that the following code seems to work but I’ve only ever run it once so be careful. Put it in the top-level instead of packaging it up in a function? What about self-confident code? Do I just have a huge blind spot for these things, though? I recently learned that TypeScript has two syntaxes for declaring object types. I use them both regularly, but I never spared a conscious thought for their concurrent existence. I would use one to evoke OCaml-ness and the other, Java-ness. Total autopilot. All vibes.
a
i'm finding it hard to imagine connotation without emotion; which (clearly) is unnecessary in the parts of the programme that deliver machine instructions (so far!) -- but there's space for it in the parts of the programme that are mean to be read, admired, spread, taught, debated, timecapsuled, encultured...
t
The best thing I've learned from following @jkoppel is that the design of a program is something different from the code. Sometimes it's not even possible to recover the design from just the source code: https://www.pathsensitive.com/2018/01/the-design-of-software-is-thing-apart.html. But you can make your intentions clearer, and one way is through the connotations of your code. The programmatic structures and the variable names that you choose both communicate something about the design. I believe most of the bugs that I've written in the past year happened because the design of a component changed and the implementation didn't. At that point, the code may still "work" just fine in its current form (i.e., it returns the correct output for any input). But if so, it works by coincidence rather than by design. Another way to say this is that the connotations of the code implicitly make promises about the behavior. And if those promises are no longer guaranteed by the design, it becomes very easy to create bugs by calling a function in a way that seems natural, but has unintended side effects.
i
In (human) language, where do connotations come from? Do they emerge from popular usage? Somewhere else? Multiple factors? Would connotational semantics come from a similar source?
j
Not in the programming languages themselves (see also: content-free grammars), but sometimes at the meta level between the programmers (see: examples upthread).
e
Would connotational semantics come from a similar source?
I think this is a fascinating question, and also points to the phrase “semantics” being a wee bit overloaded in English, maybe? Like, there is a semiotics to a program — • the “physical” source symbolizes a program’s intent • but then also it’s compilation or reduction for execution is sort of the purpose behind it made “real” As for where connotations come from, they are the exciting bit of programming to me, I think — the connotation of an image, say, is varied and dependent on how it’s interpreted, and what you understand to inform that image — the more abstract the image, the more you can sorta say the connotation is “closer” to alignment with the image itself. With a program when do you start thinking about a it’s connotations? When it’s source in an editor? When it’s been compiled? When it’s been run?
m
There's the old joke that "a sufficiently determined programmer can write Fortran-77 in any language". Learning the syntax of a language is pretty easy (or at least straightforward). What takes longer is learning the 'spirit' of a programming language. Or learning common idioms in how particular tasks are done in a programming language.
p
In (human) language, where do connotations come from? Do they emerge from popular usage?
My first guess would be that they emerge from the frequent usage of a word or phrase in combination with some other word, phrase, or idea. When this happens often enough, the word or phrase evokes images or feelings associated with the other word, phrase, or idea.
s
What if it’s the other way around? We are so used to using language — and especially so if we are trained in programming — thinking with a “voice” in our heads that we can’t imagine what it was like before we learned our first language. But we learned it. We were not born with it. The meaning primitives we started with that enabled us to make enough sense of the world around us to learn a language must therefore be based on something else. Ergo “meaning”, in the sense how a sentence makes sense to us, is itself just a metaphor for something ineffable that goes on under the hood in our subconscious mind long before concepts and words pop up in our consciousness. So maybe it’s not that the connotations emerge from the words, but that the words always carry additional residue of those thinking primitives that never quite perfectly match the words and ultimately make human language so much more ambiguous than any language based on strict formalism. In case you can’t tell, I’m a huge fan of cognitive linguistics which has lots more to say about all that (in contrast to generative linguistics, which is what you partially learn in computer science, with grammars, Chomsky et al.).
s
In Python you can use either lists or tuples for a list of objects, but tuples are typically for a heterogenous collection and lists are for homogenous collections. (Yes lists are also mutable but consider the use case where you are not mutating the list). I think this is connotation? The question I'd ask is is connotation for the machine possible? Or only for the human reader?
i
If you write code in a way that's meant to play nicely with, say, branch prediction, I think that's connotation, not denotation.