search
LoginSignup
0
Help us understand the problem. What are the problem?

More than 1 year has passed since last update.

Elixir その2 Advent Calendar 2020 Day 14

posted at

updated at

[Elixir] "Hello"と'Hello'

この記事は Elixir その2 Advent Calendar 2020 14日目です。

先日は@torifukukaiou さんの「GigalixirでPORTを4000以外の値にするのはだめよ (Elixir)」でした。
@torifukukaiou さん13日間お疲れさまでした。しばらく休憩してください。

Elixir楽しいです。少しでも多くの方とその楽しみを共有したいものです。日頃、色んな人のメモにお世話になっているので、僕も勉強した内容をどんどんアウトプットしていこうと思います。

はじめに

Elixirではシングルクオート('Hello')とダブルクオート("Hello")が同義ではないと何となく分かっていながら、シングルクオートを使う機会が今まで全くありませんでした。使わないので結局、よくわからないまま放置してありました。

が、NervesでIoTのシリアル通信の勉強をしていて戸惑うことがあったので、学んだ内容を軽くメモをしました。

因みにNervesでのIoT開発/電子工作はかなり楽しいので興味のある方には#NervesJP Advent Calendar 2020をおすすめします。

戸惑ったこと

シリアル通信でStringの文字一つ一つをバイトとして送信する際に、StringからCharlistへの変換が必要であること。それを理解してなかった。

# データ送信関数イメージ
iex> send_byte = fn x -> IO.puts("#{x}を送信") end

# 失敗イメージ
iex> "Hello" |> Enum.each(send_byte)
** (Protocol.UndefinedError) protocol Enumerable not implemented for "Hello" of type BitString. This protocol is implemented for the following type(s): RingLogger.CircularBuffer, HashSet, Range, Map, Function, List, Stream, Date.Range, HashDict, GenEvent.Stream, MapSet, File.Stream, IO.Stream
    (elixir 1.11.2) lib/enum.ex:1: Enumerable.impl_for!/1
    (elixir 1.11.2) lib/enum.ex:141: Enumerable.reduce/3
    (elixir 1.11.2) lib/enum.ex:3461: Enum.each/2

# 成功イメージ
iex> 'Hello' |> Enum.each(send_byte)
72を送信
101を送信
108を送信
108を送信
111を送信
:ok

""''の違いを確認

マッチ演算子=

"Hello" = 'Hello'
** (MatchError) no match of right hand side value: 'Hello'

比較演算子==

"Hello" == 'Hello'
false

IO.inspect

iex> IO.inspect("Hello")
"Hello"

iex> IO.inspect('Hello')
'Hello'

なんの情報も得られませんでした。

iexのi ヘルパー関数

iex> i "Hello"

Term
  "Hello"
Data type
  BitString
Byte size
  5
Description
  This is a string: a UTF-8 encoded binary. It's printed surrounded by
  "double quotes" because all UTF-8 encoded code points in it are printable.
Raw representation
  <<72, 101, 108, 108, 111>>
Reference modules
  String, :binary
Implemented protocols
  Collectable, IEx.Info, Inspect, List.Chars, String.Chars
iex> i 'Hello'

Term
  'Hello'
Data type
  List
Description
  This is a list of integers that is printed as a sequence of characters
  delimited by single quotes because all the integers in it represent printable
  ASCII characters. Conventionally, a list of Unicode code points is known as a
  charlist and a list of ASCII characters is a subset of it.
Raw representation
  [72, 101, 108, 108, 111]
Reference modules
  List
Implemented protocols
  Collectable, Enumerable, IEx.Info, Inspect, List.Chars, String.Chars

具体的な違いが見えてきました。

# a string: a UTF-8 encoded binary
"Hello" = <<72, 101, 108, 108, 111>> 

# a list of integers
'Hello' = [72, 101, 108, 108, 111]   

データタイプが全く違うんですね。

is_binary("Hello") #=> true
is_binary('Hello') #=> false

is_bitstring("Hello") #=> true
is_bitstring('Hello') #=> false

is_list("Hello") #=> false
is_list('Hello') #=> true

"Hello"'Hello'に変換

Kernel.to_charlistで可能。

"Hello" |> to_charlist                    #=> 'Hello'
<<72, 101, 108, 108, 111>> |> to_charlist #=> 'Hello'

'Hello'"Hello"に変換

Kernel.to_stringで可能。

'Hello' |> to_string                  #=> "Hello"
[72, 101, 108, 108, 111] |> to_string #=> "Hello"

IO.inspectのオプションを変えてみる

iex> IO.inspect("Hello", binaries: :as_binaries)
<<72, 101, 108, 108, 111>>
"Hello"

iex> IO.inspect('Hello', charlists: :as_lists)
[72, 101, 108, 108, 111]
'Hello'

もう一回正しい理解でデータ送信

iex> send_byte = fn x -> IO.puts("#{x}を送信") end
#Function<44.97283095/1 in :erl_eval.expr/5>

iex> "Hello" |> to_charlist |> Enum.each(send_byte)
72を送信
101を送信
108を送信
108を送信
111を送信
:ok

さいごに

因みにやりたかったことはLCDに書き込むときのこういうやつです。

ここまでまとめてみて、やっと基本が分かってきました。更にElixir - Getting Startedの例のようなUnicodeに対応する場合は文字によっては隠れたバイトがあるので、もう少しややこしい場合があるようです。

Elixir その2 Advent Calendar 2020 初日[87, 101, 32, 97, 114, 101, 32, 116, 104, 101, 32, 65, 108, 99, 104, 101, 109, 105, 115, 116, 115, 44, 32, 109, 121, 32, 102, 114, 105, 101, 110, 100, 115, 33]
に改めて戻ってみると、おもしろいです。

明日は「[Elixir] GenServerのCallとCast」です。引き続き、Elixirを楽しみましょう。

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
What you can do with signing up
0
Help us understand the problem. What are the problem?