YAMAGUCHI::weblog

海水パンツとゴーグルで、巨万の富を築きました。カリブの怪物、フリーアルバイター瞳です。

or-done-channelでコードの可読性を上げる

はじめに

こんにちは、キーボード自作おじさんです。このエントリはGo Advent Calendar 2017の4日目の記事です。 今年のエントリーは大作が並ぶアドベントカレンダーの休憩用のエントリーと思っていただければ幸いです。

Goの並列処理のパターン

Goが公開されてからもう8年になり、Goが得意とする並列処理にもGo特有のパターンなどがコミュニティ内で蓄積されてきました。 その中でもよく聞くものとしては

  • for-select loop
  • or-channel
  • or-done-channel
  • tee-channel
  • fan-in, fan-out

などがあります。今日はその中でも or-done-channel について書こうと思います。

どういうときに or-done-channel を使うか

上限の数が決まっているような処理を行う場合に

  • データのソースからの入力が終わってしまった場合(channelのcloseに対応)
  • 上限の数に達してしまった場合(doneに対応)

のいずれかに当てはまる場合に便利なパターンです。

rangeを使う場合

まずchannelがcloseするまでの処理を行う場合は、range キーワード使って forループを回すのが便利で可読性も高いです。

for v := range ch {
    something(v)
}

しかし、この場合は処理の上限に達してしまった場合が対応できません。何らかの形で ch と done の両方を受けてあげる必要があります。

for-select loopだけを使う場合

そうなるとGoで複数のchannelを使った並行処理を書こうと思った場合には for-select loop が一番良く出てくるので、それを書きたくなります。

LOOP:
for {
    select {
    case v, ok := <-ch:
        if !ok {
            break LOOP
        }
        something(v)
    case <-done:
        break LOOP
    }
}

これでとりあえず希望の処理は書けるのですが、どうも見た目が大きくなってしまいます。そこでこの処理を別途まとめて、rangeの書き方に持ち込むのが or-done-pattern です。

or-done-channel

deferの性質を使って done が来ても ch からのデータ取得が終わった場合にも、かならず stream を close しています。これで得られる stream が閉じられたどうかだけ意識すればよくなるため、普通に range のパターンに持ち込めるわけです。

func orDone(done <-chan bool, ch <-chan Data) <-chan Data {
    stream := make(chan Data)
    go func() {
        defer close(stream)
        for {
            select {
            case <-done:
                return
            case v, ok := <-ch:
                if !ok {
                    return
                }
                stream <- v
            }
        }
    }()
    return stream
}

for v := range orDone(done, ch) {
    something(v)
}

Goはシンプルな文法ながら、 goroutinechannelfordefer などの機能をうまく組み合わせると非常に柔軟な書き方ができるので、こういった書き方との出会いがたくさんあって日々勉強になっています。皆さんも面白いパターンを知ったらぜひ教えてください。

明日は @cia_rana さんです。

package.el + use-package で落ち着いた

はじめに

こんにちは、Arch Linuxをメインマシンにしてから毎日盆栽の手入れのように設定ファイルを弄くりましているものです。今日はEmacsのパッケージ管理を結局 use-package にしましたという話です。

アンケートを取ってみた

なんの気なしにアンケートを取ってみたら100人以上の方にご回答頂きました。ありがとうございました。結構 package.el だけの人っていうのは多いなあという印象でした。

なんでuse-packageも使うようにしたか

次のような考え方が前提にありました。

  • 外部コマンドに依存したくない
  • 依存パッケージの管理を別ファイルで行いたくない
  • init.elで管理対象の拡張は領域ごとに分けておきたい

1つめの条件でCaskが消えました。2つめの条件でel-getは若干対象外としました。 package.elだけの場合、custom変数が保存される、ということだったけど、複数台のマシンで共有してたら中身がところどころ抜けてしまい、あまり信頼できない状態になってしまったのでやめました。

use-packageの設定

まず init.el は、とりあえず use-package.el が入ってなかったらインストールして、あとは必要に応じて use-package で拡張を呼び出しています。 :ensure t によって自動でインストールされるのは便利ですね。

(require 'package)
;; Added by Package.el.  This must come before configurations of
;; installed packages.  Don't delete this line.  If you don't want it,
;; just comment it out by adding a semicolon to the start of the line.
;; You may delete these explanatory comments.
(package-initialize)

;;;;; add melpa and orgmode for packages
(setq package-archives
      '(("gnu" . "http://elpa.gnu.org/packages/")
    ("melpa" . "http://melpa.org/packages/")
    ("org" . "http://orgmode.org/elpa/")))

(unless package-archive-contents
  (package-refresh-contents))
;;;;; ensure to use use-package
(when (not (package-installed-p 'use-package))
  (package-install 'use-package))
(require 'use-package)

;;;;; init-loader
(use-package init-loader
  :ensure t
  :config
  (init-loader-load "~/.emacs.d/inits"))

しばらくはこんな感じでやってこうと思います。いまのところ野良拡張の必要に迫られることなく使ってるけど、もし必要になったら、そのときは el-get の利用を考えます。

外部ディスプレイの設定をする

はじめに

こんにちは、最近自宅のメインPCをArch Linuxにしたものです。予想外にあっさりArch Linuxの設定ができたので、Linuxデスクトップ環境の進化はすごいなと感心しています。XPS13''(9350)でArch Linuxを動かしていますが、その外部ディスプレイの設定をしたのでメモしておきます。

USB Type-C - HDMI変換コネクタ

ハードウェアは相性があるので動作報告しといたほうがいいかなと思ったのでメモ。

これは2年弱前くらいから使ってたやつで、もともとWindows 10を動かしてたときに外部ディスプレイにつなぐために買ったやつだけど、もちろんArch Linuxを入れたあとでも動作しています。

XRandR

XRandRを使う場合はターミナルで簡単に設定できます。ここではeDP1というディスプレイとDP1というディスプレイがconnectedになっていて、DP1のほうが外部ディスプレイです。

% xrandr
Screen 0: minimum 8 x 8, current 1920 x 1080, maximum 32767 x 32767
eDP1 connected primary (normal left inverted right x axis y axis)
   1920x1080     59.93 +
   1400x1050     59.98  
...
   720x405       60.00  
   640x360       60.00  
DP1 connected 1920x1080+0+0 (normal left inverted right x axis y axis) 530mm x 300mm
   1920x1080     60.00*+  60.00    50.00    59.94  
   1920x1080i    60.00    50.00    59.94  
...
   640x480       75.00    60.00    59.94  
   720x400       70.08  
DP2 disconnected (normal left inverted right x axis y axis)
HDMI1 disconnected (normal left inverted right x axis y axis)
HDMI2 disconnected (normal left inverted right x axis y axis)
VIRTUAL1 disconnected (normal left inverted right x axis y axis)

認識されているディスプレイがわかったら、また同様に xrandr コマンドにオプションをつけて配置します。

% xrandr --output eDP1 --auto --output DP1 --auto --left_of eDP1

これで外付けディスプレイをラップトップのディスプレイの左側に配置した感じになりました。便利。

また普段はラップトップを閉じた状態で外部ディスプレイにつないでいるので、その場合は備え付けディスプレイはオフにした状態で外部ディスプレイをprimaryにしたい。

% xrandr --output eDP1 --off --output DP1 --auto --primary

こんな感じで試してみていい感じになったらshellscriptなどに残して自動化などをすると良いでしょう。

ARandR

しかしもっと便利なものがあって、ARandRというRandRのGUIがあり、これで同様の設定ができました。 f:id:ymotongpoo:20171113004214p:plain

XRandRのときと同様にOutputのメニューから認識されているディスプレイを選択して、下の画面で任意の位置に配置します。配置が終わったらApplyすれば、そのような画面構成になります。レイアウトが気に入ったらセーブすれば次回以降呼び出すときに便利。

参考

Caskからpackage.elに戻ってきた

はじめに

こんにちは、Emacsユーザーです。最近開発マシンをArchにしたことに合わせて、設定ファイルの掃除などをしてるんですが、いろいろ考えた結果自分の用途ではCaskとかel-getとか要らないなって思ったんで、デフォルトで入ってるpackage.elに戻ってきました。

package-install-selected-packages

Emacs 25.1から M-x package-list-packages のリストからインストールしたパッケージに関してはカスタム変数の package-selected-packages に記録されるようになりました。(init.el とかに勝手に追加される)

この変数がきちんと管理されてれば、新しい環境で新規に立ち上げたときにも、M-x package-install-selected-packages とすれば普通にパッケージを持ってきてくれるので、依存する外部コマンドとかがなくて楽。

Customの書き込み/読み込み先

init.el に書き込まれるのが鬱陶しいなと思っていたら、同様のことを思っている人が大勢いました。

(setq custom-file (expand-file-name "custom.el" user-emacs-directory))
(when (file-exists-p custom-file)
  (load custom-file)

これを init.el に書いて、Customが書き込んだ内容を .emacs.d/custom.el に移して無事完了。

参照

ウィンドウマネージャーをcinnamonからi3にした

はじめに

自宅のラップトップマシンをArch Linuxして、ウィンドウマネージャーをi3に変更した。それと同時に会社のLinux環境もi3に変更して、だいぶシンプルにいろいろとできるようになった。備忘録としてなにをしたか残しておく。

追加でインストールしたパッケージ

  • i3
  • i3lock
  • pulseaudio-control
  • xbacklight
  • playerctl
  • networkmanager

設定ファイル

# This file has been auto-generated by i3-config-wizard(1).
# It will not be overwritten, so edit it as you like.
#
# Should you change your keyboard layout some time, delete
# this file and re-run i3-config-wizard(1).
#

# i3 config file (v4)
#
# Please see https://i3wm.org/docs/userguide.html for a complete reference!

set $mod Mod4

# Font for window titles. Will also be used by the bar unless a different font
# is used in the bar {} block below.
font pango:Inconsolata 10
exec --no-startup-id fcitx
exec --no-startup-id "feh --bg-scale $HOME/.config/i3/wallpaper.jpg"

# This font is widely installed, provides lots of unicode glyphs, right-to-left
# text rendering and scalability on retina/hidpi displays (thanks to pango).
#font pango:DejaVu Sans Mono 8

# Before i3 v4.8, we used to recommend this one as the default:
# font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1
# The font above is very space-efficient, that is, it looks good, sharp and
# clear in small sizes. However, its unicode glyph coverage is limited, the old
# X core fonts rendering does not support right-to-left and this being a bitmap
# font, it doesn’t scale on retina/hidpi displays.

# Use Mouse+$mod to drag floating windows to their wanted position
floating_modifier $mod

# start a terminal
bindsym $mod+Return exec i3-sensible-terminal

# kill focused window
bindsym $mod+Shift+q kill

# start dmenu (a program launcher)
bindsym $mod+d exec dmenu_run
# There also is the (new) i3-dmenu-desktop which only displays applications
# shipping a .desktop file. It is a wrapper around dmenu, so you need that
# installed.
# bindsym $mod+d exec --no-startup-id i3-dmenu-desktop

# change focus
bindsym $mod+j focus left
bindsym $mod+k focus down
bindsym $mod+l focus up
bindsym $mod+semicolon focus right

# alternatively, you can use the cursor keys:
bindsym $mod+Left focus left
bindsym $mod+Down focus down
bindsym $mod+Up focus up
bindsym $mod+Right focus right

# move focused window
bindsym $mod+Shift+j move left
bindsym $mod+Shift+k move down
bindsym $mod+Shift+l move up
bindsym $mod+Shift+semicolon move right

# alternatively, you can use the cursor keys:
bindsym $mod+Shift+Left move left
bindsym $mod+Shift+Down move down
bindsym $mod+Shift+Up move up
bindsym $mod+Shift+Right move right

# split in horizontal orientation
bindsym $mod+h split h

# split in vertical orientation
bindsym $mod+v split v

# enter fullscreen mode for the focused container
bindsym $mod+f fullscreen toggle

# change container layout (stacked, tabbed, toggle split)
bindsym $mod+s layout stacking
bindsym $mod+w layout tabbed
bindsym $mod+e layout toggle split

# toggle tiling / floating
bindsym $mod+Shift+space floating toggle

# change focus between tiling / floating windows
bindsym $mod+space focus mode_toggle

# focus the parent container
bindsym $mod+a focus parent

# focus the child container
#bindsym $mod+d focus child

# switch to workspace
bindsym $mod+1 workspace 1
bindsym $mod+2 workspace 2
bindsym $mod+3 workspace 3
bindsym $mod+4 workspace 4
bindsym $mod+5 workspace 5
bindsym $mod+6 workspace 6
bindsym $mod+7 workspace 7
bindsym $mod+8 workspace 8
bindsym $mod+9 workspace 9
bindsym $mod+0 workspace 10

# move focused container to workspace
bindsym $mod+Shift+1 move container to workspace 1
bindsym $mod+Shift+2 move container to workspace 2
bindsym $mod+Shift+3 move container to workspace 3
bindsym $mod+Shift+4 move container to workspace 4
bindsym $mod+Shift+5 move container to workspace 5
bindsym $mod+Shift+6 move container to workspace 6
bindsym $mod+Shift+7 move container to workspace 7
bindsym $mod+Shift+8 move container to workspace 8
bindsym $mod+Shift+9 move container to workspace 9
bindsym $mod+Shift+0 move container to workspace 10

# reload the configuration file
bindsym $mod+Shift+c reload
# restart i3 inplace (preserves your layout/session, can be used to upgrade i3)
bindsym $mod+Shift+r restart
# exit i3 (logs you out of your X session)
bindsym $mod+Shift+e exec "i3-nagbar -t warning -m 'You pressed the exit shortcut. Do you really want to exit i3? This will end your X session.' -b 'Yes, exit i3' 'i3-msg exit'"
# lock screen (requires 'i3lock' package)
bindsym $mod+Control+l exec i3lock

# audio (requires 'pactl' package)
bindsym XF86AudioRaiseVolume exec --no-startup-id pactl set-sink-volume 0 +5%
bindsym XF86AudioLowerVolume exec --no-startup-id pactl set-sink-volume 0 -5%
bindsym XF86AudioAudioMute exec --no-startup-id pactl set-sink-mute 0 toggle 

# display (requires 'xbacklight' package)
bindsym XF86MonBrightnessUp exec xbacklight -inc 10
bindsym XF86MonBrightnessDown exec xbacklight -dec 10

# music control (requires 'playerctl' package)
bindsym XF86AudioPlay exec playerctl play
bindsym XF86AudioPause exec playerctl pause
bindsym XF86AudioNext exec playerctl next
bindsym XF86AudioPrev exec playerctl previous

# resize window (you can also use the mouse for that)
mode "resize" {
        # These bindings trigger as soon as you enter the resize mode

        # Pressing left will shrink the window’s width.
        # Pressing right will grow the window’s width.
        # Pressing up will shrink the window’s height.
        # Pressing down will grow the window’s height.
        bindsym j resize shrink width 10 px or 10 ppt
        bindsym k resize grow height 10 px or 10 ppt
        bindsym l resize shrink height 10 px or 10 ppt
        bindsym semicolon resize grow width 10 px or 10 ppt

        # same bindings, but for the arrow keys
        bindsym Left resize shrink width 10 px or 10 ppt
        bindsym Down resize grow height 10 px or 10 ppt
        bindsym Up resize shrink height 10 px or 10 ppt
        bindsym Right resize grow width 10 px or 10 ppt

        # back to normal: Enter or Escape
        bindsym Return mode "default"
        bindsym Escape mode "default"
}

bindsym $mod+r mode "resize"

# Start i3bar to display a workspace bar (plus the system information i3status
# finds out, if available)
bar {
        status_command i3status
}

おまけ

FnキーとMultimediaキーの主従が希望と逆(F1-F12が通常だとMultimediaキーとして動作していて、Fnキーを押さないとF1-F12として動作しない)だったので、どうやったらデフォルトの設定を逆にできるんだろうと思っていろいろ調べてたんだけど、なんのことはない、Fn+ESCを押せばいいだけだった。

XPS 13'' (9350)だとBIOS設定(Fn Lock)で挙動を変更できる。

参照