Saturday, February 13, 2016

Ruby Scope

Ruby has perhaps a new variation on the bad old LISP thing of some functions evaluating in the context where they're called rather than in a self-contained scope.

class Foo
  def initialize(a)
    @a = a
  end

  def do_wat(m)
    wat_helper(m)
  end
end

def wat_helper(n)
  @n = n
  @a = "lol"
end

f = Foo.new(1)
p f  #
f.do_wat(2)
p f  #


wat_helper() isn't a member function of any class, so where do its member variables @n and @a bind? Whatever instance context it's called from, apparently.

This is powerful and terrible. On the one hand I could write some nice utility functions for maintaining a tree or a doubly-linked-list and inside any instance maintain @prev, @next, @less, @greater, @parent, and so on. That's great for re-use of the data structure utility functions.
But it's also terrible because I now kinda need to not trust any function I call because it might clobber or pollute my instance variables. There's a notion out there that one should code-review any open source project you're thinking about importing to see if its code is up to your standards. Practically things tend to get in on reputation and basic demonstration of working right. But if code I'm importing can potentially clobber my data structures in this weird way I feel like I should be extra suspicious of it.
https://bolson.org/~bolson/2016/wat_scope.rb

Friday, February 5, 2016

More Rails WAT

If something appears to be in English plural form, Rails will treat it differently. I have more or less come to peace with the Go convention of Capitalized Fields And Methods being 'public' and lower case fields and methods being 'package' scope (in Java/C++ terms). It's weird, but okay I guess. It's a hard and enforced rule, which is probably better than the Python convention of methods and fields starting with '_' being visible but please don't use them please treat them as package or private and not for you.

In my config/routes.rb I wound up with two lines via various experiments in building a rails app:

  resource :event
  resources :event_wats


I wrote a migration by hand which does `create_table :event ...` and I called the setup tool `rails generate scaffold EventWat ...` to create a second table with a migration `create_table :event_wats ...`. I read about this utility in a new tutorial I was reading today and wondered what all I would get from that automated setup. It writes a lot of files!

I also discovered that 'resource' vs 'resources' is a thing. A 'resource' is apparently some kind of singleton. I guess there would only ever be one row of it in the database table. 'resources' get the rest of the REST path bits to deal with multiple rows in the table, list an index of things, etc.

The "Convention over Configuration" doctrine necesitates tools like this! It's like the canonical form of certain special C++ functions, only times twenty. A table of a certain name needs route, model, controller, and view files and classes of certain names.

Rails pedagogy seems to be heavy on tutorial and light on reference documentation. I tried to build my 'event' table based on reference documentation and I missed that the tools had moved on and using `rails generate scaffold` was the new right way to set up things. The reference documentation for setting up a table missed talking about how it ties into the rest of the documentation, and whether the table name should be plural or not and where plural naming matters.

"Convention over Configuration" makes me mad. If I `rails generate scaffold` I get a full set of files that hang together by convention. If I piece things together manually I’ll probably guess the convention wrong at some point and I can’t configure things to hang together because there is no configuration. I just need to rename my classes or tables or files or something until I meet the strange demands of the evil wizard who designed this ‘convention’.

CoC makes the learning curve steeper. It's like I can't just learn one part of the system, I have to learn the whole system at once and the convention it lives by. CoC hides what is going on, and that is not good. I want to have all the moving parts visible and traceable by inspection of the code in a project. I don't want spooky action at a distance. I don't want things to work magically. If something is going to be made easier, I want the APIs designed to make explicit configuration as easy as possible.

Monday, February 1, 2016

Ruby

Here's a line of Ruby from the Rails library:

result = execute schema_creation.accept td

'td' is a variable in local scope
'schema_creation' is a function on the current object, '.accept' is a function on that object, we're passing 'td' to '.accept'
'execute' is a function on the current object, we're passing the result of 'schema_creation.accept td' to 'execute'

I would prefer to write that, for clarity:

execute(schema_creation().accept(td))

Python would insist on the explicit current-object reference:

self.execute(self.schema_creation().accept(td))

But I'm fine with implicit-this of C++ or Java style.

In the Ruby as written (found in Rails/ActiveRecord source) I look at that line of code and think, "What are these words?" There are no hints! I need a Ruby IDE that has evaluated my codebase and looks at the context in any code block to tell me what the things in it are. This is even worse than large Python codebases I'm used to where I have to dig through several files of call chain to figure out what type a parameter being passed in is. Here I don't even know which words are methods or functions or data.

Friday, June 12, 2015

The Rust Programming Language (vs Go)

Reading about the Rust language and finding a bunch of design decisions I disagree with.

1. Named values are by default immutable. In every other language* ‘const’ is a keyword to set that, but in Rust it’s the default and you have to specifically say ‘mut’ when you want it. This is the wrong default. My code is full of variables and has a handful of constants.

2. “Safety” features make it hard to get things done. I don’t want a ‘safe’ language where it’s hard or (supposedly) impossible to do the wrong thing. This typically will also limit me and get in the way and make me inefficient when I write code that’s just fine. I want a language where it’s easy to do the right thing.

3. Excessive use of closures. It makes me worry about closure capture rules. It has exctra keywords (`move`) to deal with closure capture rules. This may be an idiomatic thing that I can actually avoid most of the time in my own code if I want to.

4. Rust fails to do safe type promotion. Compare i32 to i64. That’s safe, but Rust won’t do it. (Java gets this right. Go gets this wrong too.)

On the plus side, Rust has some basic inheritance! I can define a partially implemented interface (trait) and override the default implementation if I want to. (Go lacks this sadly.) Rust has generics too! Another nice tool for writing once and using a bunch of ways. (Another Go shortcoming.) And macros! Way better than CPP too.

I think in all Rust might be a better language than Go, but I can’t guess the ecosystem and community growth patterns right now. Rust is much newer, so I think Go is in the lead. Maybe over the next year we’ll get a clearer trend line on this stuff.

Monday, April 14, 2014

Dance/Physics

Newtonian Follow: stays at-rest/in-motion unless acted upon; has an equivalent and appropriate reaction for each action.

Quantum Follow: there is a probabilistic distribution of what they might do but you don’t know what they’re going to do until they do it. Sometimes new moves appear as if from nowhere, especially if there is a vacuum of moves.

Relativistic Follow: time is relative, for one of you the dance is over almost as soon as it starts, for the other it seems to drag on forever.

Thursday, April 10, 2014

The world is not ending, it is still yet beginning

Life has been on Earth for perhaps the last 1/5th of the history of this rock, which has been around about 1/3rd of the age of the universe.
There has been life on Earth for a billion years and our most concerted efforts of nuclear war and climate change would not eliminate it and prevent another billion years of life on Earth.
Human civilization has been around only the tiniest blink of time in all that.
We may be hitting 'Peak Oil', but I think 'Peak Humanity' is a long time in the future.
We've done all this (look around you, there's this crazy big world of six billion people and sky scrapers and space ships and favelas and sweat shops and bullet trains and everything sacred and profane) in 20,000 years. And we're accelerating. Science fiction writers try to imagine what we might be like in 1000 years or 100 years or 10 years*. Look to the future! In our history of predicting our future we have fallen short in some areas ("where's my flying car? where's our moon base?") but done vastly better in unexpected areas (like that voice controlled supercomputer in your pocket that outstrips most gadgets in Star Trek).

Yeah, I'm an optimist. I think things are going to get better.

(* I think Asimov set a big chunk of his world perhaps 20,000 years in our future but I want to discount that. It was written in the 1950s, and I think newer scifi mostly reaches less far into the future. Also Asimov's world now seems insufficiently advanced compared to our own, or other proposed nearer futures. OR, there are fictional alien races with million year civilizations making the suggestion of what might happen to us that far out; and one story I like where we join them after we mature sufficiently over a similar time span.)

Tuesday, August 27, 2013

The Right Language For The Job

The right language for the job is ... all of them. All of them at once. I want a garbage collected, bounds checked language that lets me drop down to C-level memory fiddling, runs at over 90% of the speed of plain-old-C and interprets code I type into a prompt. I want a language that checks types at compile time, except when I'm just tossing off some small quick thing. I want a functional programming language ... for about 20% of what I write, object orientation for 30% of my code, and miscellaneous glue of no particular dogma for the rest. I want a language that is terse but explicit and unambiguous. And finally I want a large standard library that helps me get done most of the common tasks I do these days, with a vast community supported set of libraries that cover even more (and most of those libraries have no dependency bloat and depend on nothing more than the standard library).
Did I forget anything?