Austin Story

Ruby, Rails and Javascript Blog

Powered by Genesis

Javascript Var Definitions Gotcha

December 19, 2016 By Austin Story Leave a Comment

This is one of the most common gotchas in Javascript.

What does this code do inside of a function?

‘var a = b = 0;’

Since javascript is right associative for assignments, at first glance you might expect it to create and set the variables a and b to 0. But there is a subtle gotcha hidden here. It actually does this

var a; //compile step initializes memory for a

b = 0; //we are in a scope, since b is not initialized in this scope (compile step misses it), javascript will go up the scope chain, assuming no parent scopes have b variable, the global scope will initialize var b for us and send it back.
a = b;

So more englishy, a is functionally scoped to the local function because it has the var in front of it. b is defined implicitly so it is put on the global scope.

Here is an example that demonstrates this further

[code]
function foo() {
var a = b = ‘assign in foo’;
function bar() {
var c = d = ‘assign in bar nested in foo’;
c; // ‘assign in bar nested in foo’
d; // ‘assign in bar nested in foo’
}
bar();
a; // ‘assign in foo’
b; // ‘assign in foo’
c; // ReferenceError, c only available in bar function
d; // ReferenceError, d available in bar and globally
}

foo();

a; // ReferenceError, because a is functionally scoped to the foo function
b; // ‘assign in foo’
c; // ReferenceError, because c is functionally scoped to the bar function
d; // ‘assign in bar nested in foo’
[/code]

After the invocation of foo in the code above, both b and d are now global variable.

Filed Under: Javascript Tagged With: gotchas, Javascript

What is a thunk in javascript?

October 25, 2016 By Austin Story 2 Comments

A thunks is a function that contains all of the context (state, functions, etc) it will need in order to carry out some sort of logic in the future.

Another way to say that, they are a function closure that begins with all of the arguments it will need in order to execute. You just don’t want to execute it now, it will be sometime in the future.

Synchronous Example

[code]
const add = (x,y) => x + y;

const thunk = () => add(1,2);

thunk() // 3
[/code]

 

Asyncrhonous

[code]
const addAsync = (x,y,callback) => {
setTimeout(function() { callback(x + y) }
}

var thunk = (callback) => addAsync(10,15,callback);

thunk( function() {
sum; // 25
}
[/code]

Filed Under: Javascript, Theory Tagged With: Javascript, thunk

Confident Ruby

October 16, 2016 By Austin Story Leave a Comment

I just finished reading Confident Ruby for the second time and wanted to capture the lessons from it. The first time I read this book was (i think) beginning/mid 2013. I am really happy I went through it again, I learned some really good things to add to my toolbelt.

  1. Cast your inputs and outputs – In order to avoid constantly checking for Nil, Integer, Array, etc, just cast or munge the data you have into the format you need.  For instance, instead of returning nil, a single item or a collection, be nice and return Array(return_value).  It will help the user on the other side be more certain of what they are dealing with.  The oppositie is true when you are receiving data, cast it so that you are certain what you are dealing with and that you are handling that assertion of format in one place.
    1. There are several built in conversion methods, use the one that makes the most sense for the problem you are solving.  For instance, if your system depends on something being a float, cast it using Float(num_or_string) otherwise use the more gracious to_f.
  2. Prefer Fetch with Blocks – It seems like a great deal of work in web apps relates to dealing with hashes.  Instead of using the standard hash[‘x’], use hash.fetch(‘x’) { default_value_or_raise }.  You can even use the raise value for if the hash does not have a value to help you find the error when you run into it in the future.  hash.fetch(‘x’) { raise :this_symbol_is_easy_to_find }.  An added benefit of using blocks, is that they are not evaluated until the fetch fails, whereas if  you do hash.fetch(‘x’, expensive_operation).  It is evaled when the fetch executes.
  3. &&= – I use ||= constantly to memoize truthy values.  Advi demonstrates using the &&= operator to assign a value to a nested attribute if the first one is present.  For instance foo &&= foo.clone ensures that a foo exists before you call the clone on it.
  4. Segregate Actions – Your code is generally doing one of 4 things; Collecting Input, Performing Work, Delivering Output, Handling Failures.  Keep those separate and when you are done with one, be done with it.
  5. Replace String With Class – As best as you can, express domain logic using Classes.  Using strings or hashes is quick, but the class will help you clarify the domain and you have the side benefit of Polymorphism to handle a lot of switching.  A great example of this is a Parameter Object.  In the book you start with a drawing a point on a map to represent a location.  This quickly expands to a FuzzyPoint (a point with a radius around it) and a StarPoint.  The classes allow the encapsulation of all of the uniqueness of these.
    1. Yield Builder Objects (197) – Instead of locking users into an api implementation, allow for a block to be passed in and yield to the block in builders.  This allows them to configure stuff you may not have accounted for.   For instance, when you create a PointBuilder to create the things above.  If it accepts a block where you yield the point to it, you can accept things like PointBuilder.new(x: 5,y: 7) { |p| p.maginitude = 75 }.  Your PointBuilder automatically can handle SOOO many more cases.
  6. Document Assumptions – When assuming something will be a certain way, document it using code.  I.e. cast float using Float or if you want a collection use Array.  This will increase clarity for you and other programmers.
  7. Receive Policies Instead of Data (206) – When you have different ways you want to handle edge cases (for instance, return false, log differently, raise in some cases), instead of passing in flags for :ignore_errors, :log_stuff, :raise prefer to accept a block that specifies what you want to happen.  The in the rescue area you can do something like if block_givin? then yield(thing, error) else raise end
  8. Call back instaed of returning (211)  – A callback on success is more meaningful than a true false return value.  In the book we have a import_purchase method that is used a lot.  That import_purchase cna accept a block and on_success, on_reduntant, on_fail yield itself to the block along with a the message (on_success, etc).  The block passed in then defines what happens on those cases.  Completely inverts the control so that instead of hard wiring in what is going to happen, you dictate it view the block that is passed in.
  9. Catch and Throw – This is a concept i see somethings, always obscurely.  But you can create a block catch(:done) method end.  Then if you throw(:done) it will go up the call stack until there is something that catches it and continue executing below it.

Filed Under: Books, Ruby Tagged With: book review, confident ruby, ruby

  • « Previous Page
  • 1
  • 2
  • 3
  • 4
  • …
  • 11
  • Next Page »

Categories

  • AngularJS
  • Books
  • Devise
  • Elasticsearch
  • ES6
  • Information Security
  • Integrations
  • Javascript
  • Linux
  • Minitest
  • PhoneGap
  • Programming
  • React
  • Redux
  • Ruby
  • Ruby on Rails
  • Stripe
  • Testing
  • Theory
  • TypeScript
  • Uncategorized
  • Vue
  • Webpack