Hacker Newsnew | past | comments | ask | show | jobs | submit | more binrec's commentslogin

Musk is a great hype man in an industry where hype is the difference between success and failure. If he'd started out in a different field, he could've been the next Tom Ford or Zaha Hadid. That's not necessarily a statement about the quality of his or his companies' work - Zaha Hadid does not make nice buildings, and I wouldn't buy a Tesla - but it's difficult to say whether Tesla would've succeeded if not for Musk's hype... and the point of great hype men is that people buy into the hype.

On balance, having a hype man for [PayPal Mafia voice] innovation in the world of atoms seems like a good thing. Musk may not be the best person for the role, but you probably have to be a little crazy to want to be a celebrity in the first place.


> I guess you could totally do it from mobile. But then you have to fight the app store's distribution/marketing model.

I don't know much about the mobile world, so this may be a stupid question, but could you route around the app store problem by making a progressive web app?

I assume a backend of some sort would be necessary, since JS in the browser is a pretty limited environment, but if Chalkinator Desktop is handling your server setup anyway, it could install a personal backend on it for you, and the PWA could talk to that.


My skillset is native iOS apps so it'd be going against my strengths to make a PWA. Plus i'm skeptical of their usability. Having said all that: I mulled it over overnight, and i could use an extra private S3 bucket as the 'backend' for my app, therefore having both desktop and mobile versions with the same 'drafts' prior to publishing. That could really work I think, however it's more work than i was thinking of doing.


Decomposition of glyph sequences in phonetic transcription alphabets (e.g. IPA representations of phonemes) into phonological feature sets.

Existing attempts to solve this problem are hackish and difficult to customize: they typically treat each glyph as a set of features and handle diacritics and digraphs by naive composition and awkward special-casing. They also aren't written with an eye to customization in either alphabet or featural model: they typically map an ad-hoc extension of IPA to an ad-hoc featural model.

I think a natural improvement would be to develop a specification language in which each individual glyph (base character or diacritic) is a function from a feature set to a feature set, with Haskell-style pattern-matching to allow graceful handling of digraphs and context-sensitive diacritics - although syntactic sugar for digraphs would in practice be required for usability. Ideally it would also be possible to map feature sets to feature sets, in order to preserve a human-readable intermediate form (e.g. "unvoiced dental plosive") which is later mapped to the more customary binary features.

In addition to the utility for phonological databases and the like, this would also enable more rigorous testing of crosslinguistic feature sets: every feature set is implicitly a set of proposed linguistic universals and existence claims. If two segments have the same featuralization, they should never contrast in a given language; if they do, the featuralization is unsound. And if a featuralization proposes the existence of many contrasts that aren't attested anywhere, it could probably stand to be optimized.

But most of my interest in this comes from my work on a phonological database. The database needs some method of handling featuralization to facilitate feature-based search, and I just haven't seen a good way to do that yet.


Chrome's Ctrl+F behavior is damned annoying for handling linguistic data. When I search for ʰ (aspiration), I don't want h (the letter, which appears in some of the column headers and most of the notes entries) - conflating the two makes searching for ʰ practically worthless. If I couldn't turn off "ASCII characters match everything that looks vaguely like them" in Google Sheets (i.e. enable regex search), I wouldn't use Google Sheets.

...and now that I've complained about it I notice that there are extensions to enable regex search in the browser itself, nice


Easier to read for whom?

I have pretty bad eye floaters, and they're more visible in bright light. Having crud bouncing around my entire field of vision does not make for an easy or strain-free reading experience, so I enable dark mode whenever it's an option. I found checking Zulip at work pretty unpleasant until I realized I could enable dark mode.

If you're running a scientific study and basing your conclusions on the average of all participants, you might not pick up on things like that. And if you're running a scientific study on people with normal vision, a sufficiently strict definition of "normal vision" guarantees that you won't pick up on that, although the studies in question probably didn't use so strict a definition.

Even if dark mode is "scientifically worse" for most people, whatever that means, it's a useful accommodation. In fact, the Nielsen Norman Group article that this post links to argue against dark mode recommends dark mode as an accommodation for people with vision impairments.


Yes, I'm aware. A school friend of mine was almost blind and he enabled the Windows white on black accessibility setting to make using the PC easier. I'm not arguing against that.


https://neocities.org/ has a free tier. It's limited (no arbitrary filetype uploads, no custom domains), but convenient and easy to use.


A few weeks ago I got curious about the phonological development of Rotokas and figured I'd see if any reconstruction could be done on the North Bougainville languages. The only documentation I could find for Ramopa and Askopan at all were Rosetta Project Swadesh lists on archive.org - talk about coverage!


The DC area is pretty suburbanized. It's not uncommon for people who work in DC to have hour-long commutes - when I lived there, I met people who commuted to DC from as far out as Frederick and Mt Airy - but the MARC is (in my experience) reliable and some of the suburbs aren't bad. Zillow has $300k-$400k houses in Germantown.


Interesting map.

The methodology probably wouldn't be comparable to Tyshchenko's, but there is an estimate for the lexical distance between Tocharian and the other Indo-European language families (10.2307/601651) - Tocharian comes out closest to Germanic and Greek.

Then again, Tocharian wasn't spoken anywhere near Europe when it was attested, so it isn't strictly within the scope of the map - but it's unclear how it got there. The most popular view, as far as I know, is that it was the second family to branch off of Indo-European, after Anatolian, but Adams showed that it shares some innovations with Germanic (the reflexes of syllabic resonants and the expansion of the singulative function of the n-stems to adjectives) and Greek (a locative dual *-oisi, represented in the Tocharian B genitive dual), and Eric Hamp placed Tocharian in a 'Northern Indo-European' subgroup with Germanic, Balto-Slavic, and Albanian.


It's technically possible to write in a concatenative style in a non-concatenative language, but in most cases, it's nowhere near idiomatic. How would you define a function that squares a number in a concatenative style in Javascript?

Here's the best I can come up with:

  function compose(...funcs) {
    return stack => funcs.reduce((acc, cur) => cur(acc), stack)
  }

  function dup(stack) {
    stack.push(...[,,].fill(stack.pop()))
    return stack;
  }

  function mul(stack) {
    stack.push(stack.pop() * stack.pop())
    return stack;
  }

  const square = () => compose(dup, mul)

  console.log(square()([4]))
Then again, this could be a trick question someday - if the pipeline proposal goes through, it'll be possible to write idiomatic concatenative Javascript. (If you want to play with the pipeline operator, see here: https://defseg.io/etc/pipeline.html) You'd still need to define all your functions as accepting a stack parameter, but you wouldn't need a compose function, so you could do something like this:

  function dup(stack) {
    stack.push(...[,,].fill(stack.pop()))
    return stack;
  }

  function mul(stack) {
    stack.push(stack.pop() * stack.pop())
    return stack;
  }

  const square = stack => stack |> dup |> mul

  console.log([4] |> square)
  console.log([2] |> square |> square)
Now to write an ECMA proposal for recursive combinators... /s


This is actually completely incorrect. Concatenative still retains immutability for parameters. It is a subset of functional programming.

You are using a stack which is not immutable.

A lot of javascript programmers think they are doing functional programming but they don't get the essence of it. Yes you know map, yes you know reduce. But you don't get it.

functional programming is in essence a mathematical function rather than a procedural function. If you can fit your entire program into a single expression or a single function without computational steps or procedures you have achieved functional programming.

Immutability is a side effect of converting everything into a single mathematical expression. Concatenative programming and functional programming are the same thing as imperative programming BUT with more restrictions so of course you can do concatenative programming in javascript AND you can be idiomatic.

You are overcomplicating the concept. Literally:

  function square(x){
       return x*x
  }
is still concatenative.

all concatenative programming is, is using the compose operator to compose your functions into a single function.

for the given:

  function a(x){
       return x*2
  }

  function b(x){
       return x*x
  }
if your goal is to compute (2x)^2

procedural is this:

  var y = 1;
  y = a(y);
  y = b(y);
  //literally a list of procedures mutating a value. Order matters. 
  console.log(y);

functional (without concatenative):

  const x = 1;
  const y = a(x);
  const z = b(y);
  console.log(z);
Above, the functions are applied on defined immutable variables. Order doesn't matter as long as you keep all definitions the same. While order happens sort of as a consequence to this, the concept for functional programming is to get rid of procedures.

concatenative (still a valid functional program):

  const c = a |> b
  console.log(c(1));
In the above, a function application is only used here as the last step. The IO step where functional AND concatenative programming breaks down, but literally for concatenative programming your entire programming should be all made up of function definitions and composed functions and no declared variables and no applied functions. Just apply one function in the last step for IO and your program is concatenative.

Javascript has been giving bootcampers completely wrong ideas about functional programming and what it is. Learn a real functional programming lang to actually get it. Haskell is a good one.

Also your examples literally defeat the purpose of functional and concatenative programming. It makes the code worse. I would literally not think concatenative programming or functional programming is better if I saw that code for the first time. I would avoid functional programming like the plague if it caused your code to blow up into a mess like that. I'm not here to stretch my brain just to square a number.


>You are using a stack which is not immutable.

Yes, but that's beside the point. I said "style", not "paradigm". The basic structure, not the totality of the thing. I don't know what CS researchers would think of this distinction, but it seems convenient to have in practice.

You can use a functional style in Javascript without insisting on pure immutability throughout your entire project, and there are advantages to being able to do so. There are also advantages to being able to use a concatenative style, which is why the pipeline operator was proposed.

It would be possible to rewrite that code to use an immutable stack, but for the purpose of illustration - specifically, illustrating that there isn't currently a good way to write in a concatenative style in Javascript - I don't think it's necessary. You can use the style without the paradigm. (Besides, the reference implementation of Joy mutates the underlying stack variable, and if the way to get a concatenative paradigm in standards-compliant, runs-in-a-browser Javascript is to Greenspun's Tenth Law a concatenative language...)

The better option would've been not to use a stack at all, and illustrate it with integers, as you've done here. But you'd still need some way to manage multiple variables to use a concatenative idiom to compute 2x^y.

>Also your examples literally defeat the purpose of functional and concatenative programming. It makes the code worse.

Right. You can follow the rules of the paradigm in Javascript, once you've written enough of an interpreter for a concatenative language to let you do so, but it'll make your code worse. But there are languages that are designed for the paradigm - and in them, you can write good code that follows the rules of it.

>Javascript has been giving bootcampers completely wrong ideas about functional programming and what it is. Learn a real functional programming lang to actually get it. Haskell is a good one.

Not a bootcamper - even worse, I work in a warehouse - but I might quit and become one once my stock options vest...


>Yes, but that's beside the point. I said "style", not "paradigm". The basic structure, not the totality of the thing. I don't know what CS researchers would think of this distinction, but it seems convenient to have in practice.

CS researchers would say you don't know what you're talking about. Your "style" actually made things worse. You can follow the paradigm IN javascript and make your code more concise and better. Your points are true about writing an interpreter but they are not applicable in the javascript case and most cases as well. The CS term you are looking for is "Sugar". There is no sugar in javascript for compose thus it it slightly more awkward to do functional or concatenative programming in javascript than say haskell.

The pipeline operator is sugar for something that is close to compose... However it is still very convenient to simply define a compose function even without sugar for concatenative programming in javascript.

>You can use a functional style in Javascript without insisting on pure immutability throughout your entire project

Functional programming IS immutable programming the two are one and the same. Where it gets a little iffy is "pure" functional programming and "impure" functional programming. That's usually just referring to IO. Again, you don't know what you're talking about.

When you use the map or reduce you are not doing functional programming as a paradigm nor as a style. You're simply using a function. Map exists in functional programming as a higher order function, it also exists in procedural programming as a higher order function because Map can be implemented with a for loop which is a procedural primitive.

>The better option would've been not to use a stack at all, and illustrate it with integers, as you've done here. But you'd still need some way to manage multiple variables to use a concatenative idiom to compute 2x^y.

A stack isn't even relevant. You did nothing by introducing it except introducing how to do things in a more complicated way.

Dual parameters are handled in lambda calculus through currying. It's even easier in javascript as javascript supports recursion. Again you don't know what you are talking about.

  function timesTwo(x){
       return x * 2;
  }

  function xToYPower(x){
       function result(y){
            return y === 0? 1 : x*result(y-1);
       }
       return result
  }
  
  // ex: 3^2 ===> xToYPower(3)(2)
 
  function compose2(g, h){
       return x => g(h(x));
  }

  const x = 3;
  const y = 5;
  console.log(compose2(times2, xToYPower(x))(y))
  //2*(3^5)

  // pipeline syntax shown below; 
  //my mistake in the earlier comment, I thought pipeline was the 
  // compose operator. It is not... it is actually the apply operator. Which with a 
  //little modification can be used as compose or similarly to compose. 
  
  console.log(y |> xToYPower(x) |> timesTwo);

See? Concatenative programming in javascript. And it's not less convenient.

Haskell is the idiomatic language for typed functional/concatenative programming. This is what it looks like:

  timesTwo :: Int -> Int
  timesTwo x = 2 * x

  xToTheY :: Int -> Int -> Int
  xToTheY _ 0 = 1
  xToTheY x y = x * (xToTheY (y - 1))

  result = let x = 3
               y = 5
             in (timesTwo . (xToTheY x))(y)
  
  main = println result

  // - the "." is the compose operator. It is this operator that spawns the name
  //     "point free programming" and is the main "sugar" feature used for 
  //      concatenative programming
  // - haskell curries functions with multiple parameters automatically, hence 
  //      (xToTheY x) returns a function that that accepts y and will apply y to x 
  //      to get x^y. 


which is essentially the same thing just with more "sugar" but you can see that it's not a huge step up from javascript.

> It would be possible to rewrite that code to use an immutable stack, but for the purpose of illustration - specifically, illustrating that there isn't currently a good way to write in a concatenative style in Javascript

There is a good way, like I just showed you above. It's not that far from haskell which is THE definitive language for these styles of programming.

I'm not even an advocate for javascript. (TBH I ate the language). So you can see here that what I'm saying is unbiased.

>Not a bootcamper - even worse, I work in a warehouse

Don't worry it's not worse. It's the same. Bootcamps literally teach you everything you can get off the internet in a very superficial way. Anyone can learn javascript bootcamp or not. Get better and get off javascript.


>Functional programming IS immutable programming the two are one and the same.

Yes, and many imperative languages allow you to use, in an idiomatic manner, a functional style that avoids mutable state, even though these languages aren't designed around the functional paradigm, and don't require you to adhere purely, in the colloquial sense that means "strictly" or "completely" but has fewer letters, to it. And the reason for this is that people have taken ideas from languages that were designed to be functional rather than imperative.

If you want to bring up map and reduce, what's their genealogy? Did the imperative world get the idea from ALGOL? Maybe they did, but I'd be surprised.

>See? Concatenative programming in javascript. And it's not less convenient.

It still isn't great. To avoid stepping outside the paradigm, you have to be willing to curry every function that needs multiple parameters. And I don't know what that recursion is doing there - presumably I don't know what I'm talking about again, but it seems to me that the entire body of `xToYPower` could be replaced with `return y => x y`.


>If you want to bring up map and reduce, what's their genealogy? Did the imperative world get the idea from ALGOL? Maybe they did, but I'd be surprised.

Genealogy is that it's a pattern from the functional world. It's usually unused in procedural languages because they have special syntax for it like the for loop. However there is no restriction to implement map using a for loop. Therefore it is not part of the paradigm similar to how using functions in a procedural language does not mean you are doing functional programming from a stylistic perspective.

>To avoid stepping outside the paradigm, you have to be willing to curry every function that needs multiple parameters

For compose yes you are correct, it has to be done.

>And I don't know what that recursion is doing there

The recursion is doing x^y. That is the meaning of the function name.

  2^3 = 8
  3^2 = 9
  xToY(2)(3) = 8
  xToY(3)(2) = 9
>but it seems to me that the entire body of `xToYPower` could be replaced with `return y => x y`

x y with a space inbetween looks like a syntax error. I don't think it will even run.


Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: