Lazy Diary @ Hatena Blog

PowerShell / Java / miscellaneous things about software development, Tips & Gochas. CC BY-SA 4.0/Apache License 2.0

How to join nested collections with Stream API

For example, in PushOperation.java in EGit, PushOperationSpecification contains LinkedHashMap<URIish, Collection<RemoteRefUpdate>>. So you can join all remote name with Stream API like:

String specs = this.specification.getURIs().stream()
        .map(uri -> this.specification.getRefUpdates(uri))
        .collect(StringBuilder::new,
                (sb, refupdates) -> sb.append(refupdates.stream()
                        .map(remote -> remote.getRemoteName())
                        .collect(Collectors.joining(","))),
                (sb1, sb2) -> sb1.append(sb2))
        .toString();

You cannot wrap checked exceptions with lambda in Java

Context

  • You can use lambda as lazy evaluation syntax in Java.

Problem

You can wrap RuntimeException with lambda like (it shows "omit exception"):

import java.util.function.Supplier;

public class OmitRuntimeException {
    public static void main(String[] args) {
        OmitRuntimeException o = new OmitRuntimeException();
        o.wrapLambda(() -> o.throwException());
    }

    public void wrapLambda(Supplier<String> msg) {
        try {
            System.out.println(msg.get());
        } catch (Exception e) {
            System.out.println("omit exception");
        }
    }

    public String throwException() throws RuntimeException {
        if (true) {
            throw new RuntimeException();
        }
        return "";
    }
}

But you cannot wrap ordinal Exception with lambda like:

import java.util.function.Supplier;

public class OmitException {
    public static void main(String[] args) {
        OmitException o = new OmitException();
        o.wrapLambda(() -> o.throwException());
    }

    public void wrapLambda(Supplier<String> msg) {
        try {
            System.out.println(msg.get());
        } catch (Exception e) {
            System.out.println("omit exception");
        }
    }

    public String throwException() throws Exception {
        if (true) {
            throw new Exception();
        }
        return "";
    }
}

And you will get a compile error:

$ LANG=C javac OmitException.java 
OmitException.java:6: error: unreported exception Exception; must be caught or declared to be thrown
        o.wrapLambda(() -> o.throwException());
                                           ^
1 error

Solution:

Use RuntimeException, or wrap the function that thows checked exceptions with another function.

プログラムに対する指摘の受け取りかたの分類

前提:

プログラムに対する指摘への回答が全て「仕様です」で返ってくる、という笑い話は前世紀からある。 ここで、実際にはどういった回答が考えられるか。

検討観点:

  • プログラムの設計時に検討対象に挙がっていた内容か?
  • 実現可能性はあるか?
  • 実際にプログラムへ実装したか?
  • 現在の挙動になっている(機能要件上の)理由はあるか?

といった軸を観点として分類してみる。

まとめ案:

新機能追加要望に対する回答を想定して分類してみた。

# 回答 検討対象に 実現可能性 実装 今の挙動にした理由
1 仕様 挙がってた あり した ある
2 不具合 挙がってた あり した ない
3 制限事項 挙がってた ありor未検討 してない ない
4 対応不可能 挙がってた なし してない -
5 スコープ外 挙げてなかった 未検討 してない -
  1. 仕様です:そうした方がいい(あるいは他のにしない方がいい)理由があって、現在の挙動になっています。
  2. 不具合です:そうした方がいいと思って、そのように実装したつもりが、そうなっていませんでした。
  3. 制限事項です:そうした方がいいのは分かってますが、工数やら期日やら自分たちの都合の関係で実装できていません。
  4. 対応不可能です:そうなってたらいいとは思いますが、原理的に・他のプログラムとの組み合わせ的に不可能です。
  5. スコープ外です:そもそも検討対象に挙がっていません・挙げていません。

Run a command with specific user priviledge in Windows (like sudo in Unix)

Problem:

You can use runas command to run a command with specific user privilege. (Note: You have to type password into command prompt):

C:\>runas /user:domain\username cmd
Enter the password for domain\username:
Attempting to start cmd as user "domain\username" ...

But, you will get error with a command with arguments:

C:\>runas /user:domain\username net start WebClient

RUNAS USAGE:

RUNAS [ [/noprofile | /profile] [/env] [/savecred | /netonly] ]
        /user:<UserName> program

You can also use Start-Process -Verb runas with the same aim without typing password (UAC dialog will pop up for privileges):

PS > Start-Process -Verb runas cmd

But you will get an error when you want pass arguments to the command:

PS > Start-Process -Verb runas net start WebClient

Start-Process : A positional parameter cannot be found that accepts argument 'WebClient'.
At line:1 char:1
+ Start-Process <<<<  -Verb runas net start WebClient
    + CategoryInfo          : InvalidArgument: (:) [Start-Process]、ParameterBindingException
    + FullyQualifiedErrorId : PositionalParameterNotFound,Microsoft.PowerShell.Commands.StartProcessCommand

Or you will get another error when you quote the command and arguments:

PS > Start-Process -Verb runas "net start WebClient"
Start-Process : This command cannot be executed due to the error: The system ca
nnot find the file specified.
At line:1 char:14
+ Start-Process <<<<  -Verb runas "net start WebClient"
    + CategoryInfo          : InvalidOperation: (:) [Start-Process]、InvalidOperationException
    + FullyQualifiedErrorId : InvalidOperationException,Microsoft.PowerShell.Commands.StartProcessCommand

Solution:

You should quote the command and arguments in runas command:

C:\>runas /user:domain\username "net start WebClient"
Enter the password for domain\username:
Attempting to start net start WebClient as user "domain\username" ...

You should use -ArgumentList option to pass argument in Start-Process cmdlet:

Start-Process -Verb runas -ArgumentList "stop WebClient" net

You cannot have two forks from one repository in GitHub

Problem:

  • “Fork” button in GitHub forks a repository into your account.
  • You cannot rename the repository when you fork it.
  • You cannot have two repositories with identical name.

So, you cannot have two forks from one repository simultaneously.

Solution:

There is no workaround. If you want to make two forks, you have to make two GitHub account.