ruby 中“<<”运算符的用途是什么
What are the uses of the '<<' operator in ruby
我有这个示例代码,它本质上只是一些用于处理 mdii 文件的基本 classes
class Array
def to_midi(file, note_length='eighth')
midi_max = 108.0
midi_min = 21.0
low, high = min, max
song = MIDI::Sequence.new
# Create a new track to hold the melody, running at 120 beats per minute.
song.tracks << (melody = MIDI::Track.new(song))
melody.events << MIDI::Tempo.new(MIDI::Tempo.bpm_to_mpq(120))
# Tell channel zero to use the "piano" sound.
melody.events << MIDI::ProgramChange.new(0, 0)
# Create a series of note events that play on channel zero.
each do |number|
midi_note = (midi_min + ((number-midi_min) * (midi_max-low)/high)).to_i
melody.events << MIDI::NoteOnEvent.new(0, midi_note, 127, 0)
melody.events << MIDI::NoteOffEvent.new(0, midi_note, 127,
song.note_to_delta(note_length))
end
open(file, 'w') { |f| song.write(f) }
end
end
class TimedTrack < MIDI::Track
MIDDLE_C = 60
@@channel_counter=0
def initialize(number, song)
super(number)
@sequence = song
@time = 0
@channel = @@channel_counter
@@channel_counter += 1
end
# Tell this track's channel to use the given instrument, and
# also set the track's instrument display name.
def instrument=(instrument)
@events << MIDI::ProgramChange.new(@channel, instrument)
super(MIDI::GM_PATCH_NAMES[instrument])
end
# Add one or more notes to sound simultaneously. Increments the per-track
# timer so that subsequent notes will sound after this one finishes.
def add_notes(offsets, velocity=127, duration='quarter')
offsets = [offsets] unless offsets.respond_to? :each
offsets.each do |offset|
event(MIDI::NoteOnEvent.new(@channel, MIDDLE_C + offset, velocity))
end
@time += @sequence.note_to_delta(duration)
offsets.each do |offset|
event(MIDI::NoteOffEvent.new(@channel, MIDDLE_C + offset, velocity))
end
recalc_delta_from_times
end
# Uses add_notes to sound a chord (a major triad in root position), using the
# given note as the low note. Like add_notes, increments the per-track timer.
def add_major_triad(low_note, velocity=127, duration='quarter')
add_notes([0, 4, 7].collect { |x| x + low_note }, velocity, duration)
end
private
def event(event)
@events << event
event.time_from_start = @time
end
end
除了使用 <<
运算符的行外,大部分内容对我来说都非常有意义,从我的所有研究来看,使用 <<
的唯一原因是当您定义 class 那将是一个单例。那么这段代码中 <<
具体以什么方式使用?
来自https://github.com/jimm/midilib:
MIDI::Track
是包含一系列事件的轨道。
因此,使用 <<
您可以将事件添加到您的轨道中。它与
melody.events.push(MIDI::NoteOnEvent.new(0, midi_note, 127, 0))
<<
也可用于位移操作
http://calleerlandsson.com/2014/02/06/rubys-bitwise-operators/
<<
运算符可以用于按位运算(这里不太可能)或者可以在 class 中重载以匹配某些行为。在这种情况下,(可能)有一个 Array
对象,因此 event
通过此运算符被推入 @events
数组。有关此用例的更多信息 can be found here.
请注意,将来您可能会遇到使用此运算符的其他情况,但并非每次都表示相同的意思 - 这取决于库创建者。现在想到的另一个用例可以是 ActiveRecord 关系,如 has_many
,您也可以在其中使用此运算符立即将对象推送到关系并保存。关于这个的更多信息可以在 api docs here 中找到。快速示例:
class User < ActiveRecord::Base
has_many :posts
end
class Post < ActiveRecord::Base
belongs_to :user
end
然后在代码的某处你可以使用:
@post = Post.find(10)
@user = User.find(1)
@user.posts << @post
# automatically save the @post object with updated foreign key
我有这个示例代码,它本质上只是一些用于处理 mdii 文件的基本 classes
class Array
def to_midi(file, note_length='eighth')
midi_max = 108.0
midi_min = 21.0
low, high = min, max
song = MIDI::Sequence.new
# Create a new track to hold the melody, running at 120 beats per minute.
song.tracks << (melody = MIDI::Track.new(song))
melody.events << MIDI::Tempo.new(MIDI::Tempo.bpm_to_mpq(120))
# Tell channel zero to use the "piano" sound.
melody.events << MIDI::ProgramChange.new(0, 0)
# Create a series of note events that play on channel zero.
each do |number|
midi_note = (midi_min + ((number-midi_min) * (midi_max-low)/high)).to_i
melody.events << MIDI::NoteOnEvent.new(0, midi_note, 127, 0)
melody.events << MIDI::NoteOffEvent.new(0, midi_note, 127,
song.note_to_delta(note_length))
end
open(file, 'w') { |f| song.write(f) }
end
end
class TimedTrack < MIDI::Track
MIDDLE_C = 60
@@channel_counter=0
def initialize(number, song)
super(number)
@sequence = song
@time = 0
@channel = @@channel_counter
@@channel_counter += 1
end
# Tell this track's channel to use the given instrument, and
# also set the track's instrument display name.
def instrument=(instrument)
@events << MIDI::ProgramChange.new(@channel, instrument)
super(MIDI::GM_PATCH_NAMES[instrument])
end
# Add one or more notes to sound simultaneously. Increments the per-track
# timer so that subsequent notes will sound after this one finishes.
def add_notes(offsets, velocity=127, duration='quarter')
offsets = [offsets] unless offsets.respond_to? :each
offsets.each do |offset|
event(MIDI::NoteOnEvent.new(@channel, MIDDLE_C + offset, velocity))
end
@time += @sequence.note_to_delta(duration)
offsets.each do |offset|
event(MIDI::NoteOffEvent.new(@channel, MIDDLE_C + offset, velocity))
end
recalc_delta_from_times
end
# Uses add_notes to sound a chord (a major triad in root position), using the
# given note as the low note. Like add_notes, increments the per-track timer.
def add_major_triad(low_note, velocity=127, duration='quarter')
add_notes([0, 4, 7].collect { |x| x + low_note }, velocity, duration)
end
private
def event(event)
@events << event
event.time_from_start = @time
end
end
除了使用 <<
运算符的行外,大部分内容对我来说都非常有意义,从我的所有研究来看,使用 <<
的唯一原因是当您定义 class 那将是一个单例。那么这段代码中 <<
具体以什么方式使用?
来自https://github.com/jimm/midilib:
MIDI::Track
是包含一系列事件的轨道。
因此,使用 <<
您可以将事件添加到您的轨道中。它与
melody.events.push(MIDI::NoteOnEvent.new(0, midi_note, 127, 0))
<<
也可用于位移操作
http://calleerlandsson.com/2014/02/06/rubys-bitwise-operators/
<<
运算符可以用于按位运算(这里不太可能)或者可以在 class 中重载以匹配某些行为。在这种情况下,(可能)有一个 Array
对象,因此 event
通过此运算符被推入 @events
数组。有关此用例的更多信息 can be found here.
请注意,将来您可能会遇到使用此运算符的其他情况,但并非每次都表示相同的意思 - 这取决于库创建者。现在想到的另一个用例可以是 ActiveRecord 关系,如 has_many
,您也可以在其中使用此运算符立即将对象推送到关系并保存。关于这个的更多信息可以在 api docs here 中找到。快速示例:
class User < ActiveRecord::Base
has_many :posts
end
class Post < ActiveRecord::Base
belongs_to :user
end
然后在代码的某处你可以使用:
@post = Post.find(10)
@user = User.find(1)
@user.posts << @post
# automatically save the @post object with updated foreign key