Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add the concept of NULL #70

Closed
wants to merge 2 commits into from
Closed

Conversation

tristil
Copy link
Contributor

@tristil tristil commented Feb 16, 2016

Allow NULL to be referenced in formulas, and for passed-in variables to
have the value of 'null', which is evaluated as nil.

I would understand if you're not interested in this change. We need it because we want to have a function like this:

@calculator.add_function(:sum_values, :numeric, ->(*args) {
  args.reject! { |arg| arg.is_a?(String) }

  if args.none?
    ''
  else
    args.inject(BigDecimal('0.0')) do |sum, item|
      sum + (item || BigDecimal('0.0'))
    end
  end
})

... where the idea is that you only add up the values that are numeric. The reason that some charges are strings is because we are currently passing in the value of those variables as the string 'null'. This is because if the values of these variables was actually nil then the calculator would raise an unbound variable error before entering this function. And while this works, it's not great because we still have to pass back another string afterwards, requiring lots of blah != '' checks throughout our calculations.

@tristil tristil force-pushed the explicit_null branch 2 times, most recently from 6508714 to b14ded5 Compare February 16, 2016 21:30
@@ -12,6 +12,8 @@ def initialize(token)
def value(context={})
v = context[identifier]
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe it would be better to see if the context has the key identifier here, rather than checking the to see if the returned value is nil. That way, we could explicitly pass in nil as an identifier value.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That is definitely cleaner, and I agree that relying on a special string 'null' as an input is strange. The problem with the way things are written at the moment is that context has the unbound variable's key in it whether or not it was passed in as an input, because of the way that the context hash is built up here https://github.com/rubysolo/dentaku/blob/master/lib/dentaku/bulk_expression_solver.rb#L46 ... actually looking at that now, that looks like an avoidable behavior. Be right back.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Never mind, I don't see a way to avoid that behavior while keeping the recursive algorithm. So the behavior there always sets a key on the context.

It seems to me that one path forward is to build in checks for nullity into all the relevant operators, so that you would throw the unbound variable error when performing a +, -, / etc. That seems like a pain and complicates things, but I think it might have some benefits, like allowing an IF statement where the right side is irrelevant so it doesn't matter if its variable was passed or not. I won't work on that unless you think that is a good idea though.

@tristil
Copy link
Contributor Author

tristil commented Feb 17, 2016

@rubysolo Decided to go for something simpler for this PR. In the original code there were two parts within the commit:

  1. The ability to say "NULL" in a formula, which was mentioned here IS Operator for IS BLANK or IS NOT BLANK  #18 and seems generally useful, e.g. IF(blah, 1, null)
  2. The ability to pass in a variable as nil and have it be treated as NULL instead of an unbound variable
  1. is easy but 2) is actually tricky to implement as things stand. I changed this commit to just handle 1) and I'd like to keep brainstorming on 2).

Allow NULL to be referenced in formulas, which will be evaluated as nil.
This requires moving things around so that nil values are only set to
the nodes' context hash if that value was explicitly set on the
calculator. Previously every referenced variable name would be added as
a key to the context hash even it was unbound.
@tristil
Copy link
Contributor Author

tristil commented Feb 18, 2016

Came up with another commit for 2) which passes all tests. The change is a little subtle but I can't see anything wrong with it.

@rubysolo rubysolo closed this in c8abb4e Feb 18, 2016
@rubysolo
Copy link
Owner

Thanks, this is a good addition! I took NULL out of the README, since it's not really an operator or function.

@tristil
Copy link
Contributor Author

tristil commented Feb 25, 2016

@rubysolo What do you think about releasing another gem for this change? It would help us with managing our dependencies since right now we have to point at the sha in multiple gemfiles instead of in a single gemspec.

@rubysolo
Copy link
Owner

Done!

@tristil
Copy link
Contributor Author

tristil commented Feb 26, 2016

Thanks :)

@muescha
Copy link
Contributor

muescha commented Aug 8, 2016

but the implemented NULL should be documented anyway in the doc

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants