Hacker News new | past | comments | ask | show | jobs | submit | rntz's comments login

Is it ironic, though? "Right to repair" has to do with freedom, sure, but not free-as-in-beer. It doesn't mean "it costs me no money to repair things". It means "I am not prevented from repairing things". Selling stuff - including selling writing - is not incompatible with the right to repair.


> Selling stuff - including selling writing - is not incompatible with the right to repair.

apple also sells kits to repair (and components). Except they do so with high expense, such that they make the same or higher margins on those components than a new buy.

No, i don't believe that information should be gated. The right to repair requires free information, open standards, and commodity components.


True that. We are just incredibly spoiled on that part of freedom.


Have you tried writing with your non-dominant hand? I'm a righty and I find left-handed writing effectively impossible.


Yes, I have and for cursive, which is relevant when not picking up a pen, it is not that hard since you don't have to worry about precision of where exactly you place down the pen.


With Talon on Mac I believe this is possible (Mac has surprisingly nice accessibility APIs), but I don't know whether Talon on X11 can do it. If it's possible it would probably(?) involve rolling your own at-spi stuff.


Apple in general seems to really embrace accessibility. I remember using the screen reader back in middle school because it was “cool”, and now some 25 years later I can see that it was the tip of the accessibility iceberg. My iPhone has just _tons_ of accessibility features that I’ll probably never use, but that are invaluable to people experiencing all kinds of accessibility hurdles in their daily life.

I can’t speak much to windows accessibility, although Mouse Keys got me through several rough times in my life where I fried or broke my mouse in some way or another. I do think windows has improved with time, at least by accidentally triggering the screen reading in W10 more times than I’d care to admit


Is this duplication the reason why the OP is flagged? Otherwise I'm flummoxed - it seems a perfectly reasonable/normal article.


> (The same principle can be used to entice people to leave a crowded sauna — just pour water on the hot rocks to generate loyle.)

I have never come across the word "loyle" before, and googling suggests it does not exist. Does anyone know what the reference here is? Or what this is a typo for?


Apparently it's a typo for löyly a finnish word which apparently means steam [0]. The author probably only heard the word pronounced. Anyways, to find this out I merely looked up "pouring water on sauna rocks" instead of trying to look up loyle.

> The primary function of sauna rocks is to generate steam when water is poured onto them. This process, known as löyly in Finnish culture, releases the heat from the rocks in the form of steam, adding humidity to the sauna environment. This humidity helps to open the pores and create a more comfortable and relaxing experience. [1]

[0]: https://translate.google.com/?sl=auto&tl=en&text=l%C3%B6yly&... [1]: https://eligoria.com/blogs/saunas/are-you-supposed-to-put-wa...


löyly

which is a term for steam of off sauna rocks or stove

https://en.m.wiktionary.org/wiki/l%C3%B6yly


I think that's actually IBM Selectric Script, not Scribe (the images are labelled at the bottom not the top). https://fontsinuse.com/typefaces/10922/script-ibm finds two uses of it.


Quite right, thanks for the correction!


Here's a simple Haskell program to do it:

(EDIT: this code is completely wrongheaded and does not work; it assumes that when sequencing regexes, you can take the product of their sizes to find the overall size. This is just not true. See reply, below, for an example.)

    -- https://gist.github.com/rntz/03604e36888a8c6f08bb5e8c665ba9d0

    import qualified Data.List as List

    data Regex = Class [Char]   -- character class
               | Seq [Regex]    -- sequence, ABC
               | Choice [Regex] -- choice, A|B|C
               | Star Regex     -- zero or more, A*
                 deriving (Show)

    data Size = Finite Int | Infinite deriving (Show, Eq)

    instance Num Size where
      abs = undefined; signum = undefined; negate = undefined -- unnecessary
      fromInteger = Finite . fromInteger
      Finite x + Finite y = Finite (x + y)
      _ + _ = Infinite
      Finite x * Finite y = Finite (x * y)
      x * y = if x == 0 || y == 0 then 0 else Infinite

    -- computes size & language (list of matching strings, if regex is finite)
    eval :: Regex -> (Size, [String])
    eval (Class chars) = (Finite (length cset), [[c] | c <- cset])
      where cset = List.nub chars
    eval (Seq regexes) = (product sizes, concat <$> sequence langs)
      where (sizes, langs) = unzip $ map eval regexes
    eval (Choice regexes) = (size, lang)
      where (sizes, langs) = unzip $ map eval regexes
            lang = concat langs
            size = if elem Infinite sizes then Infinite
                   -- finite, so just count 'em. inefficient but works.
                   else Finite (length (List.nub lang))
    eval (Star r) = (size, lang)
      where (rsize, rlang) = eval r
            size | rsize == 0 = 1
                 | rsize == 1 && List.nub rlang == [""] = 1
                 | otherwise = Infinite
            lang = [""] ++ ((++) <$> [x | x <- rlang, x /= ""] <*> lang)

    size :: Regex -> Size
    size = fst . eval
NB. Besides the utter wrong-headedness of the `product` call, the generated string-sets may not be exhaustive for infinite languages, and the original version (I have since edited it) was wrong in several cases for Star (if the argument was nullable or empty).


Surely that fails for e.g. a?a?a?. I'd imagine you could do some sort of simplification first though to avoid this redundancy.


You're correct, and I don't see any good way to avoid this that doesn't involve enumerating the actual language (at least when the language is finite).

Oof, my hubris.


It turns out to be not that hard to just compute the language of the regex, if it is finite, and otherwise note that it is infinite:

    import Prelude hiding (null)
    import Data.Set (Set, toList, fromList, empty, singleton, isSubsetOf, unions, null)

    data Regex = Class [Char]   -- character class
               | Seq [Regex]    -- sequence, ABC
               | Choice [Regex] -- choice, A|B|C
               | Star Regex     -- zero or more, A*
                 deriving (Show)

    -- The language of a regex is either finite or infinite.
    -- We only care about the finite case.
    data Lang = Finite (Set String) | Infinite deriving (Show, Eq)

    zero = Finite empty
    one = Finite (singleton "")

    isEmpty (Finite s) = null s
    isEmpty Infinite = False

    cat :: Lang -> Lang -> Lang
    cat x y | isEmpty x || isEmpty y = zero
    cat (Finite s) (Finite t) = Finite $ fromList [x ++ y | x <- toList s, y <- toList t]
    cat _ _ = Infinite

    subsingleton :: Lang -> Bool
    subsingleton Infinite = False
    subsingleton (Finite s) = isSubsetOf s (fromList [""])

    eval :: Regex -> Lang
    eval (Class chars) = Finite $ fromList [[c] | c <- chars]
    eval (Seq rs) = foldr cat one $ map eval rs
    eval (Choice rs) | any (== Infinite) langs = Infinite
                     | otherwise = Finite $ unions [s | Finite s <- langs]
      where langs = map eval rs
    eval (Star r) | subsingleton (eval r) = one
                  | otherwise = Infinite


This depends heavily on how repetition is implemented.

With a backtracking-search implementation of regexes, bounded iteration is pretty easy.

But the linked webpage appears to compile regexes to finite state machines (it shows you their finite-state-machine, for instance), and eg [a-z]{1,256} will have 256 states: 256 times the 1 state needed for [a-z]. If [a-z] were a complex regex, you could get a combinatorial explosion.

This alone probably isn't the issue? 256 is not a very large number. But I suspect there are follow-on algorithmic issues. This is just speculation, but I wouldn't be surprised if that 256-state machine were computed by applying DFA minimization, an algorithm with worst-case exponential running time, to a more naively generated machine.


you're right. inclusion/intersection/etc. aren't actually computed via DFA but instead are computed directly on the regular expression representation itself. and large disjunctions (with 256 branches) are what is very heavy.

(it's possible to instead do these operations on DFAs but at the time i found it hard to get from an automata back to a reasonable-looking regular expression.)


^ and $ are a problem, although one with a workaround.

The standard theory of regular expressions focuses entirely on regex matching, rather than searching. For matching, ^ and $ don't really mean anything. In particular, regexp theory is defined in terms of the "language of" a regexp: the set of strings which match it. What's the set of strings that "^" matches? Well, it's the empty string, but only if it comes at the beginning of a line (or sometimes the beginning of the document). This beginning-of-line constraint doesn't fit nicely into the "a regexp is defined by its language/set of strings" theory, much the same way lookahead/lookbehind assertions don't quite fit the theory of regular expressions.

The standard workaround is to augment your alphabet with special beginning/end-of-line characters (or beginning/end-of-document), and say that "^" matches the beginning-of-line character.


title typo: "Purely Functional Data Structure" -> "Purely Functional Data Structures" (pluralization)

reads a bit weird otherwise - sounds like it's discussing a particular purely functional data structure when it's actually a survey of many (pretty much the canonical survey of them, in fact).


Thanks for pointing it out. I totally missed it. Sorry.


Join us for AI Startup School this June 16-17 in San Francisco!

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

Search: