Class: NRSER::Types::Where

Inherits:
Type show all
Defined in:
lib/nrser/types/where.rb

Overview

Where instances are predicate functions¹ as a type.

They have a #predicate block, and #test? calls it with values and returns the boolean of the result (double-bangs it ‘!!`).

Super simple, right? And easy! Why don’t we just use these things all over the place?

If you’re been around the programing block a few times, you probably saw this coming a mile away: you should avoid using them.

Yeah, sorry. Here’s the reasons:

  1. They’re opaque - it’s hard to see inside a Proc… even if you got the source code (which seems like it requires gems and involves some amount of hackery), that wouldn’t really give you the whole picture because you need to look at the binding as well… Ruby procs capture their entire environment.

    Essentially, they suck to easily and/or comprehensively communicate what they hell they do.

  2. Like When, they’re totally Ruby-centric… we can’t really serialize them and pass them off anywhere, so they’re shitty for APIs and property types and stuff that you may want or need to expose outside the runtime.

    In this sense they’re ok as implementations of types like file_path that represent an idea to be communicated to the outside world, where each system that handles that idea will need to have it’s own implementation of it.

    Lit addresses a lot of this with serializable functions, but that’s nowhere near ready to rock, and support for it would probably be added along side Where, not in place of it (since Where is probably still going to be used and useful).

So please be aware of those, and be reasonable about your Wheres.

> ¹ I say functions, because they really should be functions (same > input always gets same output, pure, etc.). > > Yeah, there’s not much stopping you from making them state-based or > random or whatever, but please don’t do that shit unless you’ve really > thought it through. And if you still do, please write me and tell me > what you thought and why it’s a reasonable idea and I’ll update this.

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods inherited from Type

#===, #builtin_inspect, #check, #check!, #explain, #from_data, #from_s, #has_from_data?, #has_from_s?, #has_to_data?, #inspect, #intersection, #name, #not, #respond_to?, #test, #to_data, #to_s, #union, #xor

Constructor Details

#initialize(**options, &predicate) ⇒ Where

Make a new NRSER::Types::Where.

Parameters:

  • &predicate (Proc<(V) => Boolean>)

    See #predicate.



74
75
76
77
78
79
80
81
82
83
84
85
# File 'lib/nrser/types/where.rb', line 74

def initialize **options, &predicate
  super **options
  
  unless predicate.arity == 1
    raise NRSER::ArgumentError.new \
      "Predicate block must have arity 1",
      predicate: predicate,
      options: options
  end
  
  @predicate = predicate
end

Instance Attribute Details

#predicateProc<(V) => Boolean> (readonly)

Predicate Proc used to test value for membership.

Returns:

  • (Proc<(V) => Boolean>)

    Really, we double-bang (‘!!`) whatever the predicate returns to get the result in #test?, but you get the idea… the response will be evaluated on its truthiness.



64
65
66
# File 'lib/nrser/types/where.rb', line 64

def predicate
  @predicate
end

Instance Method Details

#test?(value) ⇒ Boolean

Test a value for membership.

Parameters:

  • value (Object)

    Value to test for type satisfaction.

Returns:

  • (Boolean)

    ‘true` if the `value` satisfies the type.

Raises:



94
95
96
# File 'lib/nrser/types/where.rb', line 94

def test? value
  !!@predicate.call(value)
end