• Stars
    star
    108
  • Rank 321,259 (Top 7 %)
  • Language
    Ruby
  • License
    MIT License
  • Created over 9 years ago
  • Updated 8 months ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

TypeStruct

Build Status

Imitating static typed struct.

All type is checked by === method.

Motivation

I don't like Hash

p h #=> {color: 'red', width: 120, height: 200}

No name

What is this a data? We cannot know this name.

Where is this an instance from? How do we grep doing?

Bad syntax

h[:widht] #=> Cannot detect typo
#=> nil
h.dig(:widht) #=> ditto
#=> nil
h.fetch(:widht) #=> Can detect typo, But too long and cannot know suggestion from did_you_mean gem
# KeyError: key not found: :widht

Too freedom

# Where is from `who` key? Is this expected?
p h #=> {color: 'red', width: 120, height: 200, who: 'are you?'}

I like Struct

Grepable Name

Circle = Struct.new(:color, :width, :height)
circle = Circle.new('red', 120, 200)

Good syntax

circle.color
#=> 'red'
circle.widht
# NoMethodError:
Did you mean?  width
               width=

Strictly members

circle.who = "are you?"
# NoMethodError: undefined method `who='

Evolution

  • Can use keyword arguments
  • Add Type system
  • Recursive Mapping

This is the TypeStruct.

Usage

Check type

Sample = TypeStruct.new(
  str: String,
  reg: /exp/,
  num: Integer,
  any: Object,
)

sample = Sample.new(
  str: "instance of String",
  reg: "match to regexp",
  num: 10,
  any: true,
)

p sample
#=> #<Sample str="instance of String", reg="not match to regexp", num=10, any=true>

p sample.to_h
#=> {:str=>"instance of String", :reg=>"not match to regexp", :num=>10, :any=>true}

p sample.str
#=> "instance of String"

sample.string #=> NoMethodError
sample.str = 1 #=> TypeError

Recursive Mapping

Generate object from hash by recursive.

Like JSON package of golang and crystal-lang.

Point = TypeStruct.new(
  x: Integer,
  y: Integer,
)
Color = TypeStruct.new(
  code: /\A#[0-9a-f]{6}\z/i,
)
Line = TypeStruct.new(
  start: Point,
  end: Point,
  color: Color,
)

hash = JSON.parse(%({"start":{"x":3,"y":10},"end":{"x":5,"y":9},"color":{"code":"#CAFE00"}}))
line = Line.from_hash(hash)

p line
#=> #<Line start=#<Point x=3, y=10>, end=#<Point x=5, y=9>, color=#<Color code="#CAFE00">>
p line.start.y
#=> 10
line.stort
#=> NoMethodError

Four special classes

Union

Union is an object express class that some classes as one class like crystal Union.

Union#=== check all object with === method.

Foo = TypeStruct.new(
  bar: TypeStruct::Union.new(TrueClass, FalseClass)
)
p Foo.new(bar: false) #=> #<Foo bar=false>

or add Class#| method by refinements

require "type_struct/ext"
using TypeStruct::Union::Ext
Foo = TypeStruct.new(
  bar: TrueClass | FalseClass,
)

ArrayOf

ArrayOf is an object express array type.

ArrayOf#=== check all item with === method.

Bar = TypeStruct.new(
  baz: TypeStruct::ArrayOf.new(Integer),
)
p Bar.new(baz: [1, 2, 3]) #=> #<Bar baz=[1, 2, 3]>

HashOf

HashOf#=== check all keys and values with === method.

Baz = TypeStruct.new(
  qux: TypeStruct::HashOf.new(String, TypeStruct::ArrayOf.new(Integer))
)
p Baz.new(qux: { "a" => [1, 2, 3] }) #=> #<Baz qux={"a"=>[1, 2, 3]}>
p Baz.from_hash(qux: { "a" => [1, 2, 3] }) #<Baz qux={"a"=>[1, 2, 3]}>
p Baz.new(qux: { :a  => [1, 2, 3] }) #=> TypeError
p Baz.new(qux: { "a" => [1, 2, nil] }) #=> TypeError

Interface

Interface is an object for duck typing like golang interface.

Interface#=== check all method using respond_to?

Foo = TypeStruct.new(
  bar: TypeStruct::Interface.new(:read, :write)
  # or Interface.new(:read, :write) on required 'type_struct/ext'
)
Foo.new(bar: $stdin)
Foo.new(bar: 1) #=> TypeError

Mix

require "type_struct/ext"
using TypeStruct::Union::Ext
Baz = TypeStruct.new(
  qux: ArrayOf(Integer | TrueClass | FalseClass) | NilClass
)
p Baz.new(qux: [1]) #=> #<AAA::Baz qux=[1]>
p Baz.new(qux: [true, false]) #=> #<AAA::Baz qux=[true, false]>
p Baz.new(qux: nil) #=> #<AAA::Baz qux=nil>
p Baz.new(qux: 1) #=> TypeError
p Baz.from_hash(qux: [1, 2, false, true]) #=> #<A::Baz qux=[1, 2, false, true]>

Auto Generator

$ echo '{"posts": [{"number":10491,"name":"ksss"}]}' | ruby -r type_struct/generator/json
Post = TypeStruct.new(
  number: Integer,
  name: String,
)
AutoGeneratedStruct = TypeStruct.new(
  posts: ArrayOf(Post),
)

Installation

Add this line to your application's Gemfile:

gem 'type_struct'

And then execute:

$ bundle

Or install it yourself as:

$ gem install type_struct

License

The gem is available as open source under the terms of the MIT License.

More Repositories

1

orthoses

Ruby
63
star
2

digest-murmurhash

C
35
star
3

text2svg

Generate SVG data from text and font file
Ruby
34
star
4

orthoses-rails

Ruby
30
star
5

epoll

epoll(7) binding in Ruby
Ruby
22
star
6

rubocop-yard

Ruby
21
star
7

rgot

Ruby + GOlang Testing = Rgot
Ruby
20
star
8

rilo

Micro texteditor
Ruby
15
star
9

tori

Tori is a bird
Ruby
15
star
10

mruby-file-stat

File::Stat class in mruby
C
15
star
11

esa-cli

Ruby
14
star
12

active_tsv

Ruby
13
star
13

freetype

FreeType binding by ffi
Ruby
11
star
14

mruby-research

C
11
star
15

rubocop-on-rbs

Ruby
11
star
16

mruby-stringio

StringIO class for mruby
C
10
star
17

mruby-method

This library is DEPRECATED. Please use https://github.com/mruby/mruby/tree/master/mrbgems/mruby-method
C
9
star
18

raap

RBS as a Property
Ruby
9
star
19

mruby-spec

The runner for ruby/spec with mruby
Ruby
7
star
20

mruby-singleton

Singleton module in mruby based on
Ruby
7
star
21

orthoses-yard

Ruby
6
star
22

list

List in Ruby.
C
5
star
23

orthoses-typeprof

Ruby
5
star
24

mruby-signal

Signal class implementation for mruby
C
5
star
25

AsciiPack

AsciiPack is an object serialization inspired by MessagePack.
C
4
star
26

mruby-ostruct

OpenStruct in mruby based on
Ruby
4
star
27

fluent-plugin-postgres-bulk

fluent plugin for bulk insert to postgres
Ruby
3
star
28

spring-commands-ridgepole

Ruby
3
star
29

digest-siphash

Digest::SipHash is a class of message digest use algorithm SipHash.
C
3
star
30

kqueue

kqueue binding in Ruby
Ruby
3
star
31

steep-playground

Playground for Steep
Ruby
3
star
32

mysql2-client-general_log

Ruby
3
star
33

mruby-io-console

C
2
star
34

digest-stringbuffer

C
2
star
35

Scheme.js

create scheme from js
JavaScript
2
star
36

mruby-at_exit

Kernel.at_exit method on mruby
C
2
star
37

embulk-decoder-command

Embulk decoder plugin that exec another process.
Java
1
star
38

Rubylike.js

Like a Ruby
JavaScript
1
star
39

aws-sdk-rbs-generator

DEPRECATED
Ruby
1
star
40

mruby-murmurhash1

murmurhash1 digest in mruby.
C
1
star
41

limits

Const Collections of limits.h in Ruby.
Ruby
1
star
42

mruby-rake

Ruby
1
star
43

allevent.js

add all event listener
1
star
44

mruby-murmurhash2

murmurhash2 digest in mruby.
C
1
star
45

kor

Pluggable table data converter
Ruby
1
star
46

ballad-go

Go
1
star
47

Brainfuck.coffee

brainf*ck on coffee
JavaScript
1
star
48

test.js

my test unit
JavaScript
1
star
49

LIFE

game of lifes
JavaScript
1
star
50

ksss.github.com

JavaScript
1
star
51

ruby-enumerator.js

ruby-enumerator.js can use Ruby(v1.9.3) all Enumerator and Enumerable methods in javascript
JavaScript
1
star
52

walk.js

process each one char
JavaScript
1
star
53

webless

Browse web like less
JavaScript
1
star
54

mruby-io-copy_stream

IO.copy_stream method for mruby
C
1
star
55

dotfiles

Vim Script
1
star
56

mruby_build_config_checker

Print a patch build_config.rb what used head sha
Ruby
1
star
57

guess_struct

Ruby
1
star
58

lazy_method

Ruby
1
star
59

seven_languages

ansers of "seven languages in Seven Weeks: A Pragmatic Guide to Learning Programming Languages" by Bruce A. Tate
Io
1
star
60

overflow

Overflow is a class to overflow calculated as C language in Ruby.
Ruby
1
star
61

alphine-mruby

1
star