HN user

shiro

650 karma

Honolulu, HI

Lisper. Schemer. Actor.

Posts2
Comments311
View on HN

SEEKING WORK | Remote or Honolulu, HI | shiro@acm.org

SaaS back-end dev, database engine, compiler/interpreter/DSL.

Most productive with Common Lisp, Clojure, Scheme, Go, C, C++.

Past projects: https://practical-scheme.net/ShiroKawai.pdf

Github: https://github.com/shirok

Some may know me as the author of Gauche Scheme https://practical-scheme.net/gauche/, or as a Japanese translator of Paul Graham's "Hackers and Painters", Conrad Barski's "Land of Lisp", and Stuart Halloway's "Programming Clojure".

Unless you're dealing with contemporary pieces, atonal or with wild harmony, modifiers are largely the result of tonality, mode and chord progression, aren't they? I hardly need to make me "remember" them...

But yeah, I'm terrible with rhythm. I'm curious that there are different types of brain to perceive the music.

Alan Kay on Lisp 9 years ago

Don't confuse lisp-as-an-executable-device-to-think-meta and lisp-as-one-of-programming-language-choices. Alan is talking the former.

The idea---not just to think about programs per se, but to think about abstract properties and operations of certain category of programs and to be able to actually write it down---gave the exponential power to you. Lisp was the first such tool as a programming language that allowed you to break the ceiling of first-order thinking.

Nowadays there are other languages that provide meta-level tools. And once you get the idea, the language doesn't really matter; you can apply it to any language, albeit you may have to build scaffolds around it to compensate lack of language support (Cf. Greenspun's tenth rule). So, if you already got the idea through other languages, it's good for you. You'll see Lisp as an arcane prototype of modern languages.

But note: since Lisp can write meta-level description in the same language as the base language, you can top up this ladder infinitely, meaning you can think of program-generating-program, then program-generating-program-generating-program, and so on, using a single set of tools. It is indeed powerful but somewhat crude, so modern advanced languages intentionally restrict that aspect and just try to cover the sweet spot. Even if you're familiar with metaprogramming, it may still be worth to play with Lisp to see what (meta)*programming is like, to know its pros and cons, and to get the idea that might come handy someday when single-level metaprogramming isn't enough.

Lisp let’s you build the language you want to use, and have it interoperate for the rest of the ecosystem.

I suspect this strength of Lisp could have undermined improvement of Lisp compilers in long term. That is, the fact that programmers can customize the language to run efficiently for their applications put less pressure to make the existing compiler better, compared to the languages that don't give programmers such flexibility.

I've worked on performance-sensitive commercial Common Lisp applications. We employed heavy macrology so that optimal instructions were generated in the performance critical regions. Effectively, it was reimplementing part of the compiler to deal with out domain-specific meta information such as parameterized types. It worked, but came with the cost of maintenance--as if we were maintaining another layer of the compiler. It was a burden. I'm sure there have been such effort spent in many other places and eventually abandoned.

Meanwhile, languages that give less power to the programmers, put lots of efforts to improving the compiler and/or the language that work more effectively with the improved compiler, and over a few decades, they have quite sophisticated compilers.

I still mostly use Lisp-family languages at work, but sometimes wonder if the power could have adverse effect in long term.

It depends on each individual, but having looked at how my wife breastfed my son, I wouldn't say "just offer her breast". Creating milk in women's breast isn't free. They must prepare for it, and also have to take care of their breasts. My wife said it was very tiring and also got mastitis a few times. The experience may vary and I guess it'd be generally easier for young, healthy women, though.

We couldn't switch to formula because after the initial few weeks my son refused to take it. We tried various ways but couldn't make it work except breastfeeding. If we could, I wouldn't have minded preparing formula, considering how much work my wife has done for pregnancy and delivery.

Not significantly, but in the Hiragana page there are some interesting differences from standard Romanization.

Most notable one is conflation of vowel [イ] and [エ]. Often both are denoted with "i", sometimes one of them is "yi". In modern American English the sound /i/ falls in middle of Japanese イ and エ. I'm not sure in this case that it's because of that, or Ryukyu dialect had shifted vowels.

セ is denoted as "she" (usually "se"). This variation of consonant appears in some Japanese dialect.

ヒ is denoted as "fi". Might stem from old Japanese pronunciation.

Curiously, ヰ is denoted as "i" and ヱ is denoted as "yi/ye/e". Usually they are "wi" and "we", but those pronunciations have been lost in modern Japanese.

I'm not sure what source you derive from about the particularity of "sitting still". You imply that not being distracted from the given task? Or the physicality of sitting still has the benefit? (The two can be distinguished easily---if the latter is the case, "sitting still without doing anything, and just daydreaming wildly" would also have benefit.) Or you mean meditation? That's a different activity at all.

In the ADHD case, it seems about the way of processing stimuli. They (or at least my kid) need a sort of synchronization stimulus (or, outside distrubance, in the way that disturbance suppresses the divergence of hypersensitive systems) to keep his mind on rail. If no such stream of stimuli is provided, he must create one by his own. I try to make him find and build his own toolset to work with. (One of the activities, for example, is tapping along metronome while doing other tasks.)

[Edit] I see your comment in other thread that you refer to Zen meditation. I've learned meditation and I agree on its benefits, but it can't be applied to the current discussion of school setting---"sitting still listening lectures" and "sitting still meditating" are very different activities. The latter would certainly develop the ability of the former, but I'm dubious about just forcing the former.

I guess it depends on each child. My son is diagnosed ADHD and even when I'm teaching him 1-on-1 he keeps moving some part of his body or change his posture frequently. It bothered me before, but I learned that for him it's actually easier to work on the task. Restricting movement seems to make some part of his brain hyperfocused and in a short period of time his brain "shuts down".

In his school, the classroom is a kind of free style and although he has assigned desk he can choose other places to work on his task, which seems to help him a lot. (It's Montessori, so most of the time each kid works independently according to his/her own study plan.)

My knowledge of Japanese grammar is in Japanese, so I'm not certain about the English term of 主語, to be honest. We use the same term to describe 'subject' in English grammar. I used 'topic' just because the original article used it.

Your explanation of 'ga'/'wa' is spot on as far as I can understand as a layman of native speaker with standard Japanese grammar education in Japan but no advanced linguistic degree.

I'd say that, because 'wa' emphasizes the introduced subject as the center of interest, it isn't used in the subordinate clause.

Tanaka ga nihon ni itta hi. (The day Tanaka went to Japan) ; ok - the interest is on 'hi'

Tanaka wa nihon ni itta hi. ; invalid

Your third example isn't valid. It needs a bit of tweak.

Tarou ga Noriko wo mita toshokan

The particle "ga" and "wa" both introduce a topic. But in a phrase to explain a noun, we use "ga" exclusively. Your main point still holds, in a sense that "Tarou ga Noriko wo mita" is a valid sentence. But to be precise, "mita" in those two sentences are different conjugated forms; it just happens that two conjugated forms are the same in the verb "miru" (to see).

I took that the author didn't assume that experience (which seemed to be assumed in the article to be positively correlated to the length of career) was the only factor---lack of proper training, including knowing "classics", was also the issue. I tend to agree the latter premise, although I'm not sure the situation is as bad as the author describes. (The author says "I can’t think of a single developer I’ve met professionally who belong to the ACM or to IEEE". Is that really the case?)

IMHO, it's ok to lift answers from SO as long as 1) you know it's a shortcut and 2) when necessary you can trace back the history to the origin so that you can know the original frame the technique was invented and how it was modified along the line. A good solution in a certain context might not be optimal for your context, even though it has been improved by many.

The second point requires a certain level of skill---able to search and read CS papers and implement by yourself or incorporate the ideas into your domain. Without having proper training, it's difficult to acquire that kind of skill solely from skimming SO and alike. But I'd like to assume that graduate-level CS course do give such skill, and by experience you can hone it.

I do note that some answers in SO are pretty decent, with references to the original papers. When I answer online questions I try to do the same as much as possible within my ability and knowledge.

Just note here so that people unfamiliar of tsunamis won't get misconception. 50cm of tsunami is enough to wash people away. It's totally different from 50cm-high wave[1]. 1m of tsunami is deadly if you got swallowed. 3m can easily sweep two-story houses.

[1] This illustration depicts the difference: https://twitter.com/_KE_N_/status/295134747603107840/photo/1 Calculate the inertia of the water. Also mind the actual tsunami carries lots of debris so you can't easily swim in it.

Elm is Wrong 10 years ago

Not all problems are equal. Most problems can be compensated in some way or another, using abstractions. Problems that limits abstraction are grave, for it puts a glass ceiling that can't be got around.

A language designer may limit the power of abstraction intentionally; maybe the abstraction taxes performance too much; or maybe too much power scares the target users. That's a plausible choice, but that also turns some users away.

"If someone else is dictating your craft"---I see what you're at, but the line isn't that clear. I'm an actor, and I have to follow the script and directions to convey their ideas. In that sense I might be a tool, or instrument, of a director, and I'm happy to be a good tool to serve great storytelling, but there is (and should be) room where I contribute artistically, bringing something that is unique of me into the work.

I was in 3DGC productions as well. A 3D artist can be just a worker to materialize director's vision precisely as he's told, but they can also contribute the creative process to carry out the greater work.

Earth doesn't need to "fight back"---it only lets species that can cope with the changed environment take over.

Once, oxygen was toxic to most of the species on earth, when some algae started producing it by photosynthesis. If Earth fought back, we'd had very different species by now.

It's a big deal since it's not really about optimization, but more about the overall coding style and thought process.

With TCO, you start seeing functions as composable code blocks rather than something that is called and then return from. State machines are just mutually tail-calling functions---it's not that state machines are written so, but that in your mental model two are the same. And usually a program is humongous multi-layered state machine.

Suppose you want to abstract the part of the loop. You just write a generic version that tail-calls user-passed function. Users can extend the loop freely, even interlacing two independent loops by mutually calling them (which can't be done with callback model without consuming stack frames).

It's really a matter of style, but for those who get used to think in this way, not having guaranteed TCO is like writing code with one hand tied up in the back.

A kind of nitpick, but the use of dynamic-wind with custodian in the slides bothers me. Dynamic-wind shouldn't directly be used to ensure cleanup, since a continuation captured in the body may be invoked outside from dynamic-wind and the body restarts, even if resources are gone.

In the R5RS age, light users looked for try-catch construct in Scheme and could only find dynamic-wind and used it; but they're not the same. Dynamic-wind is a low-level construct that can be used to implement try-catch idiom and other stuff.

Now Scheme has guard, so it's better to use them to write cleanup stuff. It's a bit verbose, though (you have to write cleanup both in the handler and the end of body), so I personally wrote unwind-protect macro on top of it and am using it.

Maybe not as many as programming languages, but new notations do appear time to time. It's just that none has ever got as popular as the traditional notation, I guess.

I started music with classical piano and only recently started transposing instrument (bamboo flute), and am trying to get used to movable do solfege. I'm still easily confused when key change occurs or borrowed chord appears. (For the latter there are limited patterns so I should remember them, I guess.)

"In order to avoid jams" is a popular story but it's credibility has been challenged [1]. It may be worth noted that Qwerty was made before people used all fingers and touch-typed---they were likely to use just two fingers and typing speed might be quite slow in today's standard.

[1] http://gizmodo.com/qwertys-origin-story-is-a-big-fat-lie-493... (This is just a first one I found in English, but Prof. Yasuoka referred in the article publishes quite a few articles about early typewriters in Japanese, in which he lists several evidences that "jamming" wasn't the reason.)

When you're using TCO-guaranteed language like Scheme, what's important is you recognize tail position, where TCO is guaranteed. Guaranteed TCO lets you express, for example, state machine using mutually recursive functions. You do see the tail calls as gotos and you heavily rely on that while you're coding.

In that regards, I feel that tail call "optimization" is misleading, since it gives an impression that it's some kind of optional bonus the compiler gives to you. The transformation such as your gcc example is, certainly, an "optimization". If you get one, you're lucky; if you don't, fine, you can live with it. Guaranteed tail call elimination is totally different---if you don't have one, you change the way you write code.

(So, the blanket statement of "Lisp" might be inappropriate, for it's only a subset of Lisps that has guaranteed TCO.)

Quoting the author:

    With Lisp it's always been non-trivial to know when a 
    function is tail-recursive. You can't just blindly count 
    parens, you have to try to "run" the function in your mind.
To me, Lisp code is just like a tree (well, sometimes DG) and it's statically obvious where the leaves are---no need to "run" the function in mind. But maybe it's just because I get used to it; once you learned, you forget what you saw (or you didn't see) before.

Right! I tried to construct a terse example in hurry but apparently missed the mark. Usually loop comes handy when conditions and the way to extract values gets more complicated.

I use CL/Scheme/Clojure at work. I generally prefer comprehension style ('for' in Clojure, srfi-42 in Scheme) but sometimes CL's loop let me save a few nestings.

One of such patterns is when I have to accumulate multiple kind of things while I zip through the input. Somewhat contrived example: You have a hashtable that maps integer key to a list of strings. You want to scan it just once and build two lists, strings associated with odd keys and strings associated with even keys.

    ;; populate input 
    (defvar input (make-hash-table :test 'eql))
    (setf (gethash 1 input) '("ichi" "hi"))
    (setf (gethash 2 input) '("ni" "fu"))
    (setf (gethash 3 input) '("san" "mi"))
    (setf (gethash 4 input) '("yon" "shi" "yo"))
    (setf (gethash 5 input) '("go" "itsu"))

    ;; loop
    (loop for k being each hash-key in input
       when (oddp k) append (gethash k input) into odds 
       when (evenp k) append (gethash k input) into evens 
       finally (return (values odds evens)))
    ; => ("go" "itsu" "san" "mi" "ichi" "hi") and ("yon" "shi" "yo" "ni" "fu")